From 6b1ea4be88f72e53e6f1540bb7889a8b142625cf Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 2 May 2024 11:13:09 -0300 Subject: [PATCH] Fix sum tensor reduce naive --- build/cuda.cu.o | Bin 61720 -> 62712 bytes build/libtensor.so | Bin 90272 -> 90440 bytes build/tensor.o | Bin 22984 -> 22976 bytes norch/csrc/cuda.cu | 44 ++++++++++++++------------------------------ norch/csrc/cuda.h | 4 ++-- norch/csrc/tensor.h | 3 --- 6 files changed, 16 insertions(+), 35 deletions(-) diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 24a944b927afa39e8da54101b9db0d3179816b97..8bbf51d3ab58a49e5ffb3bbb3cac2193945161b9 100644 GIT binary patch delta 15115 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 delta 14690 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 E0Y6c02&3##mZdD&qqH&v+k%5yQFsU5MW6br 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 Iiy&tBKV#F4`2YX_ delta 19205 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 delta 4696 zcmZ{odu&ui6vlVj0xbw_c@4wEb_qx+1zBw&3bo4ebW9l^0;B@QE6v=(odSER#(*W{-c4Ss4^`c(PGg5opU zY5kCrC-UkB_s>6(UOBO*pvc^$`%@90EX6{7R%^*{Xg~zgMFeO>^Rs_98k=W~%{$g+ z;NUECHlG`t3&v(*Ue-^nBx_Si|LZXm$x111)o1mnwP_!kWv|&-9meKuWAlx*sUDfN zaelrvHUhyZQk9WT=X~3!tj$GTERAWJibcj|owaEjon_MIv)S0ZY-~QUHu16lx9Kr9 zmyFH$f^4jteHr<2R)M4olrjE`}cTevw5`Uxf zdZ~ul){>_{kdBN0WJe`>iOyhD_t((|l+Kdsc1v~Ceso+xhaRgCA$l*<>b^T|0`XZ= zJgfbSH<6<23&vaiKqC$~Z`*C-N)VeZ#b}7xQq@=+o$Uzbb1_0h+dL1$t%o(nLtJ|h z2_(sK2lK=0+KUX)&vMWcCd%(#6j$}12+onJU{JOSoguG!5SoaNx75|>w3Cn^8p@%4 z-DuzUw8w09htNyfuX1Qdq4Wl+%55OOZ}Si#x`NROtg9OkC%TPM-m6_m5q-;2zoK{1 zMKr^-yc^vRVJUt#{tN8J)wxL)eK9g*(}ozG*PxHiaU{c1ZD;m;4eZhOs?$=Jk6Q!# zjE6(ogXl)ERyLkye)OeVpZ$l>KQwec`dQ%a2ibjYUxP%gR0}P2ac$v&CUg>A!L+;& zcN*=3IkXQO?baOHJcQ;-HMCgg8u)M5JgyUzn>T6o-bND;lCQQpa2=pyD^Y}|Iw^)AMwX*=U>bf7S0hPuKBIbLxhN};A(~{gl+owW zM|3}k(wt(4Pta1Mi)hCW%g58 zl=TqxQf*O8 zUne6`dZSeNdfU+O=Vb&UM5`?IeTEPxI*V!bQgt;hK#J%RM)jqm8_-2`8>3SheF>sL zsx+f~wR~i@S}Ji5|pETUrf`HG!}3}v#4Q9jG-(MNPAqkNX% zG&EzWzq-27)F{<)rscDI1_`1+<yO*N_o9@vJDHa6 z-!~8;dXQ1xjiZPYJ!h$3Q9hD4NmXb+F#1^yMHgwS7!6VGZavgNkajtvI*6kk2oc@Q zC|?iz5F`4vrG8fDOjdnN%lrJ7$!eC;eZ2e$umpYNIclk2Q4GO_Qmwbt@ACs_BD$Mt zd7t+pLG)urd7qD?bD<3VY^h&SfBSLUMRa?75X3D~j6mtlQdL+RopUuEu9IOzh&D6I z`@98lqDe-1pVLSY{W1sr7F|RySnB6?N#~{t$LKC!{thihi0D<8`r0Xo5v|FgeG*Bc zPcy2wzNxpojfNr@iVUh7eKrgG8-Is}UpWerDM0(KaNB zx*rb?cyuc=%T9_tNVUuqr_j?9&O1|%NXtk}k5;(L_0bA(7SBb);x6<=!+FUGS&QWr s^yR&Ed04!M=jgl{J#_AXY7H0NQKhR01Rg@Hb!O4wW!e8WA{Z_E7urQWUjP6A diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 1dd5ed2..c24e48a 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -3,6 +3,10 @@ #include #include +#define THREADS_PER_BLOCK 128 +#define TILE_SIZE 32 +#define SHMEM_SIZE THREADS_PER_BLOCK * sizeof(float) + __host__ void cpu_to_cuda(Tensor* tensor) { float* data_tmp; @@ -55,60 +59,40 @@ __host__ void add_tensor_cuda(Tensor* tensor1, Tensor* tensor2, float* result_da cudaDeviceSynchronize(); } -__global__ void sum_tensor_cuda_kernel(float* data, float* result_data, int size) { - extern __shared__ float sdata[]; - - unsigned int tid = threadIdx.x; - unsigned int i = blockIdx.x * blockDim.x + threadIdx.x; - - sdata[tid] = (i < size) ? data[i] : 0; - __syncthreads(); - - for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1) { - if (tid < s) { - sdata[tid] += sdata[tid + s]; - } - __syncthreads(); - } - - if (tid == 0) { - result_data[blockIdx.x] = sdata[0]; - } -} __global__ void sum_tensor_cuda_kernel(float* data, float* result_data) { - __shared__ int sdata[THREADS_PER_BLOCK]; + __shared__ int partial_sum[SHMEM_SIZE]; // each thread loads one element from global to shared mem // note use of 1D thread indices (only) in this kernel int i = blockIdx.x*blockDim.x + threadIdx.x; - sdata[threadIdx.x] = data[i]; + partial_sum[threadIdx.x] = data[i]; __syncthreads(); // do reduction in shared mem for (int s=1; s < blockDim.x; s *=2) { - int index = 2 * s * threadIdx.x;; - if (index < blockDim.x) - { - sdata[index] += sdata[index + s]; + if (threadIdx.x % (2 * s) == 0) { + partial_sum[threadIdx.x] += partial_sum[threadIdx.x + s]; } __syncthreads(); } // write result for this block to global mem - if (threadIdx.x == 0) - atomicAdd(result_data, sdata[0]); + if (threadIdx.x == 0) { + result_data[threadIdx.x] = partial_sum[0]; + } } __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data) { - number_of_blocks = tensor->size / THREADS_PER_BLOCK; - sum_tensor_cuda_kernel<<>>(tensor->data, result_data, tensor->size); + int number_of_blocks = (int)ceil(tensor->size / THREADS_PER_BLOCK); + sum_tensor_cuda_kernel<<>>(tensor->data, result_data); + sum_tensor_cuda_kernel<<<1, THREADS_PER_BLOCK>>>(result_data, result_data); cudaError_t error = cudaGetLastError(); if (error != cudaSuccess) { diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index 7825534..48c87b8 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -7,8 +7,8 @@ __global__ void add_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size); __host__ void add_tensor_cuda(Tensor* tensor1, Tensor* tensor2, float* result_data); - __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int number_of_blocks); - __global__ void sum_tensor_cuda_kernel(float* data, float* result_data, int size); + __global__ void sum_tensor_cuda_kernel(float* data, float* result_data); + __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data); __global__ void sub_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size); __host__ void sub_tensor_cuda(Tensor* tensor1, Tensor* tensor2, float* result_data); diff --git a/norch/csrc/tensor.h b/norch/csrc/tensor.h index b09620d..aa8d3e9 100644 --- a/norch/csrc/tensor.h +++ b/norch/csrc/tensor.h @@ -1,9 +1,6 @@ #ifndef TENSOR_H #define TENSOR_H -#define THREADS_PER_BLOCK 128 -#define TILE_SIZE 32 - typedef struct { float* data; int* strides;