diff options
Diffstat (limited to 'cuda-kernels/genericMatrixMultiplyRow.cu')
| -rw-r--r-- | cuda-kernels/genericMatrixMultiplyRow.cu | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/cuda-kernels/genericMatrixMultiplyRow.cu b/cuda-kernels/genericMatrixMultiplyRow.cu deleted file mode 100644 index 6194492..0000000 --- a/cuda-kernels/genericMatrixMultiplyRow.cu +++ /dev/null @@ -1,289 +0,0 @@ -/* 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 (32) -#define MATRIX_N (32) -#define MATRIX_K (32) - - - -// 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::row_major> a_frag; - wmma::fragment<wmma::matrix_b, WMMA_M, WMMA_N, WMMA_K, half, wmma::row_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 * lda+ aCol , lda); - wmma::load_matrix_sync(b_frag, b + bRow * ldb+ bCol , 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*ldc + cCol , ldc, wmma::mem_row_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 *ldc + cCol , c_frag, ldc, wmma::mem_row_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("INITIAL_MATRIX_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("%.2f ",a_host_wmma[m*MATRIX_K+n]); - } - printf("\n"); - } - printf("INITIAL_MATRIX_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("%.2f ",b_host_wmma[m*MATRIX_K+n]); - } - printf("\n"); - } - printf("INITIAL_MATRIX_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("%.2f ",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)); - - int t=200000000; - while(t-->0); - - for(int m=0;m<MATRIX_M;m++){ - for(int n=0;n<MATRIX_N;n++){ - d_cal_host_wmma[m*MATRIX_N+n]=0; - for(int k=0;k<MATRIX_K;k++){ - d_cal_host_wmma[m*MATRIX_N+n]+= a_host_wmma[m*MATRIX_K+k]*b_host_wmma[k*MATRIX_K+n]; - } - d_cal_host_wmma[m*MATRIX_N+n]+=c_host_wmma[m*MATRIX_N+n]; - } - } - 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; -} - - |
