diff options
| author | aamir <[email protected]> | 2018-06-13 12:07:15 -0700 |
|---|---|---|
| committer | aamir <[email protected]> | 2018-06-13 12:07:15 -0700 |
| commit | f15fc94c25022fbceec30ab1eeb78a34101a127a (patch) | |
| tree | 0b7ff9b9b15bc068483e9146a618b362a7beba10 | |
| parent | 809a387769788d028252139d5bbd58c502c4eb43 (diff) | |
generic matrix multiply kernel passed
| -rw-r--r-- | cuda-kernels/genericMatrixMultiply.cu | 314 | ||||
| -rw-r--r-- | src/cuda-sim/instructions.cc | 58 |
2 files changed, 346 insertions, 26 deletions
diff --git a/cuda-kernels/genericMatrixMultiply.cu b/cuda-kernels/genericMatrixMultiply.cu new file mode 100644 index 0000000..95cf021 --- /dev/null +++ b/cuda-kernels/genericMatrixMultiply.cu @@ -0,0 +1,314 @@ +/* Copyright (c) 1993-2017, NVIDIA CORPORATION. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of NVIDIA CORPORATION nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +// Define some error checking macros. +#define cudaErrCheck(stat) { cudaErrCheck_((stat), __FILE__, __LINE__); } +void cudaErrCheck_(cudaError_t stat, const char *file, int line) { + if (stat != cudaSuccess) { + fprintf(stderr, "CUDA Error: %s %s %d\n", cudaGetErrorString(stat), file, line); + } +} + + +#include <mma.h> +using namespace nvcuda; + +// Must be multiples of 16 for wmma code to work +#define MATRIX_M (16) +#define MATRIX_N (16) +#define MATRIX_K (16) + + + +// The only dimensions currently supported by WMMA +const int WMMA_M = 16; +const int WMMA_N = 16; +const int WMMA_K = 16; + +__global__ void wmma_example(half *a, half *b, float *c, int M, int N, int K, float alpha, float beta) { + // Leading dimensions. Packed with no transpositions. + int lda = M; + int ldb = K; + int ldc = M; + + // Tile using a 2D grid + int warpM = (blockIdx.x * blockDim.x + threadIdx.x) / warpSize; + int warpN = (blockIdx.y * blockDim.y + threadIdx.y); + + // Declare the fragments + wmma::fragment<wmma::matrix_a, WMMA_M, WMMA_N, WMMA_K, half, wmma::col_major> a_frag; + wmma::fragment<wmma::matrix_b, WMMA_M, WMMA_N, WMMA_K, half, wmma::col_major> b_frag; + wmma::fragment<wmma::accumulator, WMMA_M, WMMA_N, WMMA_K, float> acc_frag; + wmma::fragment<wmma::accumulator, WMMA_M, WMMA_N, WMMA_K, float> c_frag; + + wmma::fill_fragment(acc_frag, 0.0f); + + // Loop over k + for (int i = 0; i < K; i += WMMA_K) { + int aRow = warpM * WMMA_M; + int aCol = i; + + int bRow = i; + int bCol = warpN * WMMA_N; + + // Bounds checking + if (aRow < M && aCol < K && bRow < K && bCol < N) { + // Load the inputs + wmma::load_matrix_sync(a_frag, a + aRow + aCol * lda, lda); + wmma::load_matrix_sync(b_frag, b + bRow + bCol * ldb, ldb); + + // Perform the matrix multiplication + wmma::mma_sync(acc_frag, a_frag, b_frag, acc_frag); + + } + } + + // Load in the current value of c, scale it by beta, and add this our result scaled by alpha + int cRow = warpM * WMMA_M; + int cCol = warpN * WMMA_N; + + if (cRow < M && cCol < N) { + wmma::load_matrix_sync(c_frag, c + cRow + cCol * ldc, ldc, wmma::mem_col_major); + + + for(int i=0; i < c_frag.num_elements; i++) { + c_frag.x[i] = alpha * acc_frag.x[i] + beta * c_frag.x[i]; + } + + // Store the output + wmma::store_matrix_sync(c + cRow + cCol * ldc, c_frag, ldc, wmma::mem_col_major); + } +} + +__global__ void convertFp32ToFp16 (half *out, float *in, int n) { + int idx = blockDim.x * blockIdx.x + threadIdx.x; + if (idx < n) { + out[idx] = in[idx]; + } +} + +int main(int argc, char* argv[]) { + float *a_fp32; + float *b_fp32; + half *a_fp16; + half *b_fp16; + + float *c; + float *c_wmma; + + float *d_host_wmma; + float *d_cal_host_wmma; + float *a_host_wmma; + float *b_host_wmma; + float *c_host_wmma; + + + cudaEvent_t startWMMA; + cudaEvent_t stopWMMA; + + + cudaErrCheck(cudaEventCreate(&startWMMA)); + cudaErrCheck(cudaEventCreate(&stopWMMA)); + + // Use tensor cores + cudaErrCheck(cudaMalloc((void**)&a_fp32, MATRIX_M * MATRIX_K * sizeof(float))); + cudaErrCheck(cudaMalloc((void**)&b_fp32, MATRIX_K * MATRIX_N * sizeof(float))); + cudaErrCheck(cudaMalloc((void**)&a_fp16, MATRIX_M * MATRIX_K * sizeof(half))); + cudaErrCheck(cudaMalloc((void**)&b_fp16, MATRIX_K * MATRIX_N * sizeof(half))); + + cudaErrCheck(cudaMalloc((void**)&c, MATRIX_M * MATRIX_N * sizeof(float))); + cudaErrCheck(cudaMalloc((void**)&c_wmma, MATRIX_M * MATRIX_N * sizeof(float))); + + d_host_wmma = (float*)malloc(MATRIX_M * MATRIX_N * sizeof(float)); + d_cal_host_wmma = (float*)malloc(MATRIX_M * MATRIX_N * sizeof(float)); + c_host_wmma = (float*)malloc(MATRIX_M * MATRIX_N * sizeof(float)); + a_host_wmma = (float*)malloc(MATRIX_M * MATRIX_K * sizeof(float)); + b_host_wmma = (float*)malloc(MATRIX_K * MATRIX_N * sizeof(float)); + + + printf("a\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_K;n++){ + a_host_wmma[m*MATRIX_K+n]= (rand()%3);///3.0; + printf("%f ",a_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + printf("b\n"); + for(int m=0;m<MATRIX_K;m++){ + for(int n=0;n<MATRIX_N;n++){ + b_host_wmma[m*MATRIX_N+n]=(rand()%3);///3.0; + printf("%f ",b_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + printf("c\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + c_host_wmma[m*MATRIX_N+n]= (rand()%3);///3.0; + printf("%f ",c_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + + cudaErrCheck(cudaMemcpy(a_fp32,a_host_wmma, MATRIX_M * MATRIX_K * sizeof(float), cudaMemcpyHostToDevice)); + cudaErrCheck(cudaMemcpy(b_fp32,b_host_wmma, MATRIX_K * MATRIX_N * sizeof(float), cudaMemcpyHostToDevice)); + + convertFp32ToFp16 <<< (MATRIX_M * MATRIX_K + 255) / 256, 256 >>> (a_fp16, a_fp32, MATRIX_M * MATRIX_K); + convertFp32ToFp16 <<< (MATRIX_K * MATRIX_N + 255) / 256, 256 >>> (b_fp16, b_fp32, MATRIX_K * MATRIX_N); + + cudaErrCheck(cudaMemcpy(c, c_host_wmma, MATRIX_M * MATRIX_N * sizeof(float), cudaMemcpyHostToDevice)); + cudaErrCheck(cudaMemcpy(c_wmma, c, MATRIX_M * MATRIX_N * sizeof(float), cudaMemcpyDeviceToDevice)); + + float alpha = 1.0f; + float beta = 1.0f; + + + printf("\nM = %d, N = %d, K = %d. alpha = %f, beta = %f\n\n", MATRIX_M, MATRIX_N, MATRIX_K, alpha, beta); + + // First: using WMMA + dim3 gridDim; + dim3 blockDim; + + // blockDim.x must be a multple of warpSize + // 128x4 means we have 16 warps and a block computes a 64x64 output tile + blockDim.x = 64; + blockDim.y = 2; + + gridDim.x = (MATRIX_M + (WMMA_M * blockDim.x / 32 - 1)) / (WMMA_M * blockDim.x / 32); + gridDim.y = (MATRIX_N + WMMA_N * blockDim.y - 1) / (WMMA_N * blockDim.y); + printf("GRID:X=%d,Y=%d\n",gridDim.x,gridDim.y); + printf("BLOCK:X=%d,Y=%d\n",blockDim.x,blockDim.y); + + printf("Running with wmma...\n"); + cudaErrCheck(cudaEventRecord(startWMMA)); + wmma_example <<< gridDim, blockDim >>> (a_fp16, b_fp16, c_wmma, MATRIX_M, MATRIX_N, MATRIX_K, alpha, beta); + cudaErrCheck(cudaEventRecord(stopWMMA)); + cudaErrCheck(cudaEventSynchronize(stopWMMA)); + + printf("\nChecking results...\n"); + cudaErrCheck(cudaMemcpy(d_host_wmma, c_wmma, MATRIX_M * MATRIX_N * sizeof(float), cudaMemcpyDeviceToHost)); + + printf("wmma:d\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + printf("%f ",d_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + printf("wmma:d\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + printf("%f ",d_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + printf("wmma:d\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + printf("%f ",d_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + printf("wmma:d\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + printf("%f ",d_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + d_cal_host_wmma[n*MATRIX_N+m]=0; + for(int k=0;k<MATRIX_K;k++){ + d_cal_host_wmma[n*MATRIX_N+m]+= a_host_wmma[k*MATRIX_K+m]*b_host_wmma[n*MATRIX_K+k]; + } + d_cal_host_wmma[n*MATRIX_N+m]+=c_host_wmma[n*MATRIX_N+m]; + } + } + printf("cal:d\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + printf("%.2f ",d_cal_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + printf("wmma:d\n"); + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + printf("%.2f ",d_host_wmma[m*MATRIX_K+n]); + } + printf("\n"); + } + int suc=1; + float relative_error; + for(int m=0;m<MATRIX_M;m++){ + for(int n=0;n<MATRIX_N;n++){ + relative_error=100*abs(d_cal_host_wmma[m*MATRIX_N+n]-d_host_wmma[m*MATRIX_N+n])/d_host_wmma[m*MATRIX_N+n]; + printf("relative_error=%f\n",relative_error); + if((int)relative_error>1) + { + printf("ERROR:\n"); + suc=0; + printf("ROW=%d,COL=%d:cpu=%f,gpgpusim=%f\n",m,n,d_cal_host_wmma[m*MATRIX_N+n],d_host_wmma[m*MATRIX_N+n]); + } + } + } + if(suc==1) + printf("COMPLETED_SUCCESSFULLY\n"); + + //int errors = 0; + //for (int i = 0; i < MATRIX_M * MATRIX_N; i++) { + // float v1 = c_host_wmma[i]; + // float v2 = c_host_cublas[i]; + // if (v1 / v2 > 1.0001 || v2 / v1 > 1.0001 || abs(v1 - v2) > 1e-5) { + // errors++; + // if (errors < 10) printf("%f %f\n", v1, v2); + // } + //} + + float wmmaTime; + cudaErrCheck(cudaEventElapsedTime(&wmmaTime, startWMMA, stopWMMA)); + printf("wmma took %fms\n", wmmaTime); + + cudaErrCheck(cudaEventDestroy(startWMMA)); + cudaErrCheck(cudaEventDestroy(stopWMMA)); + cudaErrCheck(cudaFree(a_fp32)); + cudaErrCheck(cudaFree(b_fp32)); + cudaErrCheck(cudaFree(a_fp16)); + cudaErrCheck(cudaFree(b_fp16)); + cudaErrCheck(cudaFree(c)); + cudaErrCheck(cudaFree(c_wmma)); + free(d_host_wmma); + free(c_host_wmma); + cudaErrCheck(cudaDeviceReset()); + return 0; +} + + diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index 8b66cd0..fc47d9a 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -57,7 +57,7 @@ const char *g_opcode_string[NUM_OPCODES] = { #undef OP_W_DEF }; //Using profiled information::check the TensorCoreMatrixArrangement.xls for details -unsigned thread_group_offset(int thread,unsigned wmma_type,unsigned wmma_layout,unsigned type){ +unsigned thread_group_offset(int thread,unsigned wmma_type,unsigned wmma_layout,unsigned type,int stride){ unsigned offset; unsigned load_a_row[8]={0,128,0,128,64,192,64,192}; @@ -132,24 +132,27 @@ unsigned thread_group_offset(int thread,unsigned wmma_type,unsigned wmma_layout abort(); } - + offset = (offset/16)*stride+offset%16; return offset; } -int acc_float_offset(int index,int wmma_layout){ +int acc_float_offset(int index,int wmma_layout,int stride){ int c_row_offset[]={0,1,32,33,4,5,36,37}; int c_col_offset[]={0,16,2,18,64,80,66,82}; - + int offset; + + if(wmma_layout==ROW) - return c_row_offset[index]; + offset=c_row_offset[index]; else if(wmma_layout==COL) - return c_col_offset[index]; + offset=c_col_offset[index]; else{ printf("wrong layout"); abort(); } - + offset = (offset/16)*stride+offset%16; + return offset; } void inst_not_implemented( const ptx_instruction * pI ) ; @@ -1605,7 +1608,7 @@ unsigned trunc(unsigned num, unsigned precision) { } return num; } -void mapping(int thread,int wmma_type,int wmma_layout,int type,int index,int &row,int &col,int &assg_offset){ +void mapping(int thread,int wmma_type,int wmma_layout,int type,int index,int stride,int &row,int &col,int &assg_offset){ int offset; int c_row_offset[]={0,8,0,8,4,12,4,12}; int c_col_offset[]={0,0,8,8,0,0,8,8}; @@ -1614,7 +1617,7 @@ void mapping(int thread,int wmma_type,int wmma_layout,int type,int index,int &ro int c_inside_row_offset[]={0,0,2,2,0,0,2,2}; int c_inside_col_offset[]={0,1,0,1,4,5,4,5}; - offset=thread_group_offset(thread,wmma_type,wmma_layout,type); + offset=thread_group_offset(thread,wmma_type,wmma_layout,type,stride); if(wmma_type==LOAD_A){ if(wmma_layout==ROW){ @@ -1623,6 +1626,7 @@ void mapping(int thread,int wmma_type,int wmma_layout,int type,int index,int &ro else{ offset+=64*(index/4)+index%4+128*((thread%16)/8); } + offset=(offset/16)*stride+offset%16; assg_offset=index+8*((thread%16)/8); } else if(wmma_type==LOAD_B){ @@ -1632,6 +1636,7 @@ void mapping(int thread,int wmma_type,int wmma_layout,int type,int index,int &ro else{ offset+=index+8*((thread%16)/8); } + offset=(offset/16)*stride+offset%16; assg_offset=index+8*((thread%16)/8); } else if( wmma_type==LOAD_C){ @@ -1668,7 +1673,7 @@ void mma_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) ptx_reg_t matrix_d[16][16]; ptx_reg_t src_data; ptx_thread_info *thread; - + int stride; unsigned wmma_type = pI->get_wmma_type(); unsigned a_layout = pI->get_wmma_layout(0); unsigned b_layout = pI->get_wmma_layout(1); @@ -1724,21 +1729,21 @@ void mma_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) switch(i) { case 1 ://operand 1 for(k=0;k<8;k++){ - mapping(thrd,LOAD_A,a_layout,F16_TYPE,k,row,col,offset); + mapping(thrd,LOAD_A,a_layout,F16_TYPE,k,16,row,col,offset); printf("A:thread=%d,row=%d,col=%d,offset=%d\n",thrd,row,col,offset); matrix_a[row][col]=nw_v[offset]; } break; case 2 ://operand 2 for(k=0;k<8;k++){ - mapping(thrd,LOAD_B,b_layout,F16_TYPE,k,row,col,offset); + mapping(thrd,LOAD_B,b_layout,F16_TYPE,k,16,row,col,offset); printf("B:thread=%d,row=%d,col=%d,offset=%d\n",thrd,row,col,offset); matrix_b[row][col]=nw_v[offset]; } break; case 3 ://operand 3 for(k=0;k<8;k++){ - mapping(thrd,LOAD_C,ROW,type2,k,row,col,offset); + mapping(thrd,LOAD_C,ROW,type2,k,16,row,col,offset); printf("C:thread=%d,row=%d,col=%d,offset=%d\n",thrd,row,col,offset); if(type2!=F16_TYPE){ matrix_c[row][col]=v[offset]; @@ -1842,7 +1847,7 @@ void mma_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) int row_t[8]; int col_t[8]; for(k=0;k<8;k++){ - mapping(thrd,LOAD_C,ROW,type,k,row_t[k],col_t[k],offset); + mapping(thrd,LOAD_C,ROW,type,k,16,row_t[k],col_t[k],offset); printf("mma:store:row:%d,col%d\n",row_t[k],col_t[k]); } thread = core->get_thread_info()[tid+thrd]; @@ -2909,7 +2914,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) unsigned type = pI->get_type(); unsigned wmma_type = pI->get_wmma_type(); unsigned wmma_layout = pI->get_wmma_layout(0); - + int stride; for (thrd=0; thrd < core->get_warp_size(); thrd++) { thread = core->get_thread_info()[tid+thrd]; odd=thrd%2; @@ -2920,7 +2925,8 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) unsigned nelem = src_a.get_vect_nelem(); ptx_reg_t* v= new ptx_reg_t[8]; thread->get_vector_operand_values( src_a, v, nelem ); - + stride=src2_data.u32; + memory_space_t space = pI->get_space(); memory_space *mem = NULL; @@ -2930,7 +2936,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) type_info_key::type_decode(type,size,t); printf("mma_st: thrd=%d,addr=%d, fp(size=%d), stride=%d\n",thrd,addr_reg.u32,size,src2_data.u32); - addr_t new_addr = addr+thread_group_offset(thrd,wmma_type,wmma_layout,type)*size/8; + addr_t new_addr = addr+thread_group_offset(thrd,wmma_type,wmma_layout,type,stride)*size/8; ptx_reg_t nw_v[8]; for(k=0;k<8;k++){ @@ -2942,7 +2948,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) for(k=0;k<8;k++){ if(type==F32_TYPE){ - mem->write(new_addr+4*acc_float_offset(k,wmma_layout),size/8,&v[k].s64,thread,pI); + mem->write(new_addr+4*acc_float_offset(k,wmma_layout,stride),size/8,&v[k].s64,thread,pI); printf("wmma:store:thread%d=%x,%x,%x,%x,%x,%x,%x,%x\n",thrd,v[0].s64,v[1].s64,v[2].s64,v[3].s64,v[4].s64,v[5].s64,v[6].s64,v[7].s64); float temp; @@ -2959,7 +2965,7 @@ void mma_st_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) if(wmma_layout==ROW) mem->write(new_addr+k*2,size/8,&nw_v[k].s64,thread,pI); else if(wmma_layout==COL) - mem->write(new_addr+k*32,size/8,&nw_v[k].s64,thread,pI); + mem->write(new_addr+k*2*stride,size/8,&nw_v[k].s64,thread,pI); printf("wmma:store:thread%d=%x,%x,%x,%x,%x,%x,%x,%x\n",thrd,nw_v[0].s64,nw_v[1].s64,nw_v[2].s64,nw_v[3].s64,nw_v[4].s64,nw_v[5].s64,nw_v[6].s64,nw_v[7].s64); } } @@ -2982,14 +2988,14 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) unsigned wmma_type = pI->get_wmma_type(); unsigned wmma_layout = pI->get_wmma_layout(0); int tid = inst.warp_id_func()*core->get_warp_size(); - int thrd; + int thrd,stride; ptx_thread_info *thread; for (thrd=0; thrd < core->get_warp_size(); thrd++){ thread = core->get_thread_info()[tid+thrd]; ptx_reg_t src1_data = thread->get_operand_value(src1, dst, U32_TYPE, thread, 1); ptx_reg_t src2_data = thread->get_operand_value(src2, dst, U32_TYPE, thread, 1); - + stride=src2_data.u32; memory_space_t space = pI->get_space(); memory_space *mem = NULL; @@ -2999,14 +3005,14 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) ptx_reg_t data[16]; printf("mma_ld: thrd=%d,addr=%d, fpsize=%d, stride=%d\n",thrd,src1_data.u32,size,src2_data.u32); - addr_t new_addr = addr+thread_group_offset(thrd,wmma_type,wmma_layout,type)*size/8; + addr_t new_addr = addr+thread_group_offset(thrd,wmma_type,wmma_layout,type,stride)*size/8; if(wmma_type==LOAD_A){ for(i=0;i<16;i++){ if(wmma_layout==ROW) mem->read(new_addr+2*i,size/8,&data[i].s64); else if(wmma_layout==COL){ - mem->read(new_addr+2*(i%4)+128*(i/4),size/8,&data[i].s64); + mem->read(new_addr+2*(i%4)+2*stride*4*(i/4),size/8,&data[i].s64); } else{ printf("mma_ld:wrong_layout_type\n"); @@ -3019,7 +3025,7 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) if(wmma_layout==COL) mem->read(new_addr+2*i,size/8,&data[i].s64); else if(wmma_layout==ROW){ - mem->read(new_addr+2*(i%4)+128*(i/4),size/8,&data[i].s64); + mem->read(new_addr+2*(i%4)+2*stride*4*(i/4),size/8,&data[i].s64); } else{ printf("mma_ld:wrong_layout_type\n"); @@ -3033,14 +3039,14 @@ void mma_ld_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst ) if(wmma_layout==ROW) mem->read(new_addr+2*i,size/8,&data[i].s64); else if(wmma_layout==COL) - mem->read(new_addr+32*i,size/8,&data[i].s64); + mem->read(new_addr+2*stride*i,size/8,&data[i].s64); else{ printf("mma_ld:wrong_type\n"); abort(); } } else if(type==F32_TYPE){ - mem->read(new_addr+4*acc_float_offset(i,wmma_layout),size/8,&data[i].s64); + mem->read(new_addr+4*acc_float_offset(i,wmma_layout,stride),size/8,&data[i].s64); } else{ printf("wrong type"); |
