kdsyr2k.c
Go to the documentation of this file.
#include "../include/lass.h"
/**
*
* @file kdsyr2k.c
*
* @brief LASs-DDSs kdsyr2k routine.
*
* LASs-DDSs is a software package provided by:
* Barcelona Supercomputing Center - Centro Nacional de Supercomputacion
*
* @author Pedro Valero-Lara pedro.valero@bsc.es
* @author Boro Sofranac boro.sofranac@bsc.es
* @date 2018-02-21
* @reviewer
* @modified
*
**/
/**
*
* @ingroup DDSS
*
* Performs one of the symmetric rank 2k operations:
*
* C = ALPHA * A * B**T + ALPHA * B * A**T + BETA * C or
* C = ALPHA * A**T * B + ALPHA * B**T * A + BETA * C
*
* ALPHA and BETA are scalars, C is an N by N symmetric matrix and A and B are
* N by K matrices in the first case and K by N matrices in the second case.
*
**/
/**
* @param[in]
* UPLO enum DDSS_UPLO.
* UPLO specifies the form in which C is stored:
* - Lower: Lower triangular part of C is stored. The upper traingular
* part is not referenced.
* - Upper: Upper triangular part of C is stored. The lower triangular
* part is not referenced.
*
* @param[in]
* TRANS enum DDSS_TRANS.
* TRANS specifies the operation to be performed as follows:
* - NoTrans: C = ALPHA * A * B**T + ALPHA * B * A**T + BETA * C
* - Trans: C = ALPHA * A**T * B + ALPHA * B**T * A + BETA * C
*
* @param[in]
* N int.
* N specifies the order of matrix C. N must be at least zero.
*
* @param[in]
* K int.
* With TRANS = NoTrans, K specifies the number of columns of the
* matrices A and B, and with TRANS = Trans, K specifies the number of
* rows of the matrices A and B. K must be at least zero.
*
* @param[in]
* ALPHA double.
* ALPHA specifies the scalar alpha.
*
* @param[in]
* A double *.
* A is a pointer to a matrix of dimension Na ( rows ) by Ka
* ( columns ), where Na is N and Ka is K when TRANS = NoTrans,
* and Na is K and Ka is N otherwise.
*
* @param[in]
* LDA int.
* LDA specifies the number of columns of A ( row-major order ).
* When TRANS = NoTrans then LDA must be at least max( 1, K ),
* otherwise LDA must be at least max( 1, N ).
*
* @param[in]
* B double *.
* B is a pointer to a matrix of dimension Nb ( rows ) by Kb
* ( columns ), where Nb is N and Kb is K when TRANS = NoTrans,
* and Nb is K and Kb is N otherwise.
*
* @param[in]
* LDB int.
* LDB specifies the number of columns of B ( row-major order ).
* When TRANS = NoTrans then LDB must be at least max( 1, K ),
* otherwise LDB must be at least max( 1, N ).
*
* @param[in]
* BETA double.
* BETA specifies the scalar beta.
*
* @param[in, out]
* C double *.
* C is a pointer to a matrix of dimension N by N.
* When UPLO = Uppper the strictly lower triangular part of C is not
* referenced. On exit, the upper triangular part of C is overwritten
* by the upper triangular part of the updated solution matrix C.
* When UPLO = Lower the strictly upper triangular part of C is not
* referenced. On exit, the lower triangular part of C is overwritten
* by the lower triangular part of the updated solution matrix C.
*
* @param[in]
* LDC int.
* LDC specifies the number of columns of C ( row-major order ).
* LDC must be at least max( 1, N ).
*
**/
/**
*
* @retval Success successful exit
* @retval NoSuccess unsuccessful exit
*
**/
/**
*
* @sa ddss_tile
* @sa ddss_flat2tiled
* @sa ddss_dsymflat2tiled
* @sa ddss_dsymtiled2flat
*
**/
enum LASS_RETURN kdsyr2k( enum DDSS_UPLO UPLO, enum DDSS_TRANS TRANS,
int N, int K,
const double ALPHA, double *A, int LDA,
double *B, int LDB,
const double BETA, double *C, int LDC )
{
// Local variables
int nt, kt;
int mi, ni, ki;
int Am, An;
int Bm, Bn;
int Cm, Cn;
int tile_size_m;
int tile_size_n;
int tile_size_k;
int ka;
int kb;
double beta;
// Number of tiles
if ( N % TILE_SIZE == 0 )
{
nt = N / TILE_SIZE;
}
else
{
nt = ( N / TILE_SIZE ) + 1;
}
if ( K % TILE_SIZE == 0 )
{
kt = K / TILE_SIZE;
}
else
{
kt = ( K / TILE_SIZE ) + 1;
}
/****************************
--Tile matrices declaration--
****************************/
if ( TRANS == NoTrans )
{
Am = Bm = nt;
An = Bn = kt;
ka = kb = N;
}
else
{
Am = Bm = kt;
An = Bn = nt;
ka = kb = K;
}
Cm = Cn = nt;
/***************************
--Tile matrices allocation--
***************************/
double ( *TILE_A )[An][TILE_SIZE * TILE_SIZE] = malloc(
Am * An * TILE_SIZE * TILE_SIZE * sizeof( double ) );
if ( TILE_A == NULL )
{
fprintf( stderr, "Failure in ddss_dtile_alloc for matrix TILE_A\n" );
return NoSuccess;
}
double ( *TILE_B )[Bn][TILE_SIZE * TILE_SIZE] = malloc(
Bm * Bn * TILE_SIZE * TILE_SIZE * sizeof( double ) );
if ( TILE_B == NULL )
{
fprintf( stderr, "Failure in ddss_dtile_alloc for matrix TILE_B\n" );
return NoSuccess;
}
double ( *TILE_C )[Cn][TILE_SIZE * TILE_SIZE] = malloc(
Cm * Cn * TILE_SIZE * TILE_SIZE * sizeof( double ) );
if ( TILE_C == NULL )
{
fprintf( stderr, "Failure in ddss_dtile_alloc for matrix TILE_C\n" );
return NoSuccess;
}
/*********************************************
--From flat data layout to tiled data layout--
*********************************************/
// From flat matrix A to tile matrix TILE_A
ddss_dflat2tiled( ka, LDA, A, LDA, Am, An, TILE_A );
// From flat matrix B to tile matrix TILE_B
ddss_dflat2tiled( kb, LDB, B, LDB, Bm, Bn, TILE_B );
// From flat matrix C to tile matrix TILE_C
ddss_dsymflat2tiled( N, N, C, LDC, Cm, Cn, TILE_C, UPLO );
/*************
--DSYRK tile--
*************/
// --TRANS = NoTrans & UPLO = Upper--
if ( TRANS == NoTrans )
{
if ( UPLO == Upper )
{
for ( mi = 0; mi < nt; mi++ )
{
tile_size_m = ddss_tile_size( N, mi );
for ( ni = 0; ni < kt; ni++ )
{
tile_size_n = ddss_tile_size( K, ni );
if ( ni == 0 )
{
beta = BETA;
}
else
{
beta = 1.0;
}
#pragma oss task in( TILE_A[mi][ni] ) \
in( TILE_B[mi][ni] ) \
inout( TILE_C[mi][mi] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni ) \
label( dsyr2k )
cblas_dsyr2k( CblasRowMajor,
( CBLAS_UPLO ) UPLO, ( CBLAS_TRANSPOSE ) TRANS,
tile_size_m,
tile_size_n,
ALPHA, TILE_A[mi][ni], tile_size_n,
TILE_B[mi][ni], tile_size_n,
beta, TILE_C[mi][mi], tile_size_m );
for ( ki = mi + 1; ki < nt; ki++ )
{
tile_size_k = ddss_tile_size( N, ki );
#pragma oss task in( TILE_A[mi][ni] ) \
in( TILE_A[ki][ni] ) \
in( TILE_B[mi][ni] ) \
in( TILE_B[ki][ni] ) \
inout( TILE_C[mi][ki] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni,ki ) \
label( dgemm )
{
cblas_dgemm( CblasRowMajor,
CblasNoTrans, CblasTrans,
tile_size_m,
tile_size_k,
tile_size_n,
ALPHA, TILE_A[mi][ni], tile_size_n,
TILE_B[ki][ni], tile_size_n,
beta, TILE_C[mi][ki], tile_size_k );
cblas_dgemm( CblasRowMajor,
CblasNoTrans, CblasTrans,
tile_size_m,
tile_size_k,
tile_size_n,
ALPHA, TILE_B[mi][ni], tile_size_n,
TILE_A[ki][ni], tile_size_n,
1.0, TILE_C[mi][ki], tile_size_k );
}
}
}
}
}
// --TRANS = NoTrans & UPLO = Lower--
else
{
for ( mi = 0; mi < nt; mi++ )
{
tile_size_m = ddss_tile_size( N, mi );
for ( ni = 0; ni < kt; ni++ )
{
tile_size_n = ddss_tile_size( K, ni );
if ( ni == 0 )
{
beta = BETA;
}
else
{
beta = 1.0;
}
#pragma oss task in( TILE_A[mi][ni] ) \
in( TILE_B[mi][ni] ) \
inout( TILE_C[mi][mi] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni ) \
label( dsyr2k )
cblas_dsyr2k( CblasRowMajor,
( CBLAS_UPLO ) UPLO, ( CBLAS_TRANSPOSE ) TRANS,
tile_size_m,
tile_size_n,
ALPHA, TILE_A[mi][ni], tile_size_n,
TILE_B[mi][ni], tile_size_n,
beta, TILE_C[mi][mi], tile_size_m );
for ( ki = mi + 1; ki < nt; ki++ )
{
tile_size_k = ddss_tile_size( N, ki );
#pragma oss task in( TILE_A[ki][ni] ) \
in( TILE_A[mi][ni] ) \
in( TILE_B[ki][ni] ) \
in( TILE_B[mi][ni] ) \
inout( TILE_C[ki][mi] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni,ki ) \
label( dgemm )
{
cblas_dgemm( CblasRowMajor,
CblasNoTrans, CblasTrans,
tile_size_k,
tile_size_m,
tile_size_n,
ALPHA, TILE_A[ki][ni], tile_size_n,
TILE_B[mi][ni], tile_size_n,
beta, TILE_C[ki][mi], tile_size_m );
cblas_dgemm( CblasRowMajor,
CblasNoTrans, CblasTrans,
tile_size_k,
tile_size_m,
tile_size_n,
ALPHA, TILE_B[ki][ni], tile_size_n,
TILE_A[mi][ni], tile_size_n,
1.0, TILE_C[ki][mi], tile_size_m );
}
}
}
}
}
}
// --TRANS = Trans & UPLO = Upper--
else
{
if ( UPLO == Upper )
{
for ( mi = 0; mi < kt; mi++ )
{
tile_size_m = ddss_tile_size( K, mi );
for ( ni = 0; ni < nt; ni++ )
{
tile_size_n = ddss_tile_size( N, ni );
if ( mi == 0 )
{
beta = BETA;
}
else
{
beta = 1.0;
}
#pragma oss task in( TILE_A[mi][ni] ) \
in( TILE_B[mi][ni] ) \
inout( TILE_C[ni][ni] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni ) \
label( dsyr2k )
cblas_dsyr2k( CblasRowMajor,
( CBLAS_UPLO ) UPLO, ( CBLAS_TRANSPOSE ) TRANS,
tile_size_n,
tile_size_m,
ALPHA, TILE_A[mi][ni], tile_size_n,
TILE_B[mi][ni], tile_size_n,
beta, TILE_C[ni][ni], tile_size_n );
for ( ki = ni + 1; ki < nt; ki++ )
{
tile_size_k = ddss_tile_size( N, ki );
#pragma oss task in( TILE_A[mi][ni] ) \
in( TILE_A[mi][ki] ) \
in( TILE_B[mi][ni] ) \
in( TILE_B[mi][ki] ) \
inout( TILE_C[ni][ki] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni,ki ) \
label( dgemm )
{
cblas_dgemm( CblasRowMajor,
CblasTrans, CblasNoTrans,
tile_size_n,
tile_size_k,
tile_size_m,
ALPHA, TILE_A[mi][ni], tile_size_n,
TILE_B[mi][ki], tile_size_k,
beta, TILE_C[ni][ki], tile_size_k );
cblas_dgemm( CblasRowMajor,
CblasTrans, CblasNoTrans,
tile_size_n,
tile_size_k,
tile_size_m,
ALPHA, TILE_B[mi][ni], tile_size_n,
TILE_A[mi][ki], tile_size_k,
1.0, TILE_C[ni][ki], tile_size_k );
}
}
}
}
}
// --TRANS = Trans & UPLO = Lower--
else
{
for ( mi = 0; mi < kt; mi++ )
{
tile_size_m = ddss_tile_size( K, mi );
for ( ni = 0; ni < nt; ni++ )
{
tile_size_n = ddss_tile_size( N, ni );
if ( mi == 0 )
{
beta = BETA;
}
else
{
beta = 1.0;
}
#pragma oss task in( TILE_A[mi][ni] ) \
in( TILE_B[mi][ni] ) \
inout( TILE_C[ni][ni] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni ) \
label( dsyr2k )
cblas_dsyr2k( CblasRowMajor,
( CBLAS_UPLO ) UPLO, ( CBLAS_TRANSPOSE ) TRANS,
tile_size_n,
tile_size_m,
ALPHA, TILE_A[mi][ni], tile_size_n,
TILE_B[mi][ni], tile_size_n,
beta, TILE_C[ni][ni], tile_size_n );
for ( ki = ni + 1; ki < nt; ki++ )
{
tile_size_k = ddss_tile_size( N, ki );
#pragma oss task in( TILE_A[mi][ki] ) \
in( TILE_A[mi][ni] ) \
in( TILE_B[mi][ki] ) \
in( TILE_B[mi][ni] ) \
inout( TILE_C[ki][ni] ) \
shared( TILE_A, TILE_B, TILE_C ) \
firstprivate( mi,ni,ki ) \
label( dgemm )
{
cblas_dgemm( CblasRowMajor,
CblasTrans, CblasNoTrans,
tile_size_k,
tile_size_n,
tile_size_m,
ALPHA, TILE_A[mi][ki], tile_size_k,
TILE_B[mi][ni], tile_size_n,
beta, TILE_C[ki][ni], tile_size_n );
cblas_dgemm( CblasRowMajor,
CblasTrans, CblasNoTrans,
tile_size_k,
tile_size_n,
tile_size_m,
ALPHA, TILE_B[mi][ki], tile_size_k,
TILE_A[mi][ni], tile_size_n,
1.0, TILE_C[ki][ni], tile_size_n );
}
}
}
}
}
}
/*********************************************
--From tiled data layout to flat data layout--
*********************************************/
ddss_dsymtiled2flat( N, N, C, LDC, Cm, Cn, TILE_C, UPLO );
// --Tile matrices free--
free( TILE_A );
free( TILE_B );
free( TILE_C );
return Success;
}
ddss_dflat2tiled
void ddss_dflat2tiled(int M, int N, double *A, int LDA, int MT, int NT, double(*TILE_A)[NT][TILE_SIZE *TILE_SIZE])
Definition: ddss_flat2tiled.c:68
ddss_dsymflat2tiled
void ddss_dsymflat2tiled(int M, int N, double *A, int LDA, int MT, int NT, double(*TILE_A)[NT][TILE_SIZE *TILE_SIZE], enum DDSS_UPLO UPLO)
Definition: ddss_flat2tiled.c:147
ddss_dsymtiled2flat
void ddss_dsymtiled2flat(int M, int N, double *A, int LDA, int MT, int NT, double(*TILE_A)[NT][TILE_SIZE *TILE_SIZE], enum DDSS_UPLO UPLO)
Definition: ddss_tiled2flat.c:223
kdsyr2k
enum LASS_RETURN kdsyr2k(enum DDSS_UPLO UPLO, enum DDSS_TRANS TRANS, int N, int K, const double ALPHA, double *A, int LDA, double *B, int LDB, const double BETA, double *C, int LDC)
Definition: kdsyr2k.c:124
ddss_tile_size
int ddss_tile_size(int M, int MT)
Definition: ddss_tile.c:52