From c02170731ffb8087e701392ba97270c6b4cec4e8 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 00:38:33 -0300 Subject: [PATCH 01/14] remove atomicAdd test --- norch/csrc/cuda.cu | 2 +- norch/csrc/tensor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 6908780..fdf2cb5 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -152,7 +152,7 @@ __global__ void sum_tensor_cuda_kernel_axis(float* data, float* result_data, int for (int i = 0; i < strides[target_axis]; ++i) { int index = offset + i * strides[target_axis + 1]; - atomicAdd(&result_data[outer_index * inner_size + inner_index], data[index]); + //atomicAdd(&result_data[outer_index * inner_size + inner_index], data[index]); } } } diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 221ec62..129a747 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -217,7 +217,7 @@ extern "C" { int target_axis_stride = tensor->strides[axis]; int outer_size = tensor->size / target_axis_stride; - cudaMalloc((void**)&result_data, (outer_size) * sizeof(float)); + cudaMalloc((void**)&result_data, outer_size * sizeof(float)); } sum_tensor_cuda(tensor, result_data, axis); From f25a0602946bc5e5497d4f9b3977a07d5e3c1911 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 01:06:21 -0300 Subject: [PATCH 02/14] fix sum cuda axis with atomicAdd --- build/cuda.cu.o | Bin 166672 -> 172544 bytes build/tensor.o | Bin 52456 -> 52416 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 19860 -> 20124 bytes norch/csrc/cuda.cu | 47 +++++++++++++++--------- norch/csrc/cuda.h | 2 +- norch/csrc/tensor.cpp | 14 +++---- norch/libtensor.so | Bin 220560 -> 224680 bytes test.py | 7 ++++ 8 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 test.py diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 4ed5a3e1251a6f80622bd4bd00a0eddaf3039dac..1c85a787038c01f348bb054e0e6c5c7a6c0c1191 100644 GIT binary patch delta 30261 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 dgMhP2pW}WRcaWL2}JYO%tS*!#J31_ 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 literal 52456 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 W_k7Y5_s9K@iO6^tTorrAU;YbKFYH4A delta 1808 zcmeH|OH30{6o&7anU>np@@UJW2{ib^T8trx&nRLDAa6yYMh$AFAj7L%NAWQYDv~Hl zq+S)@0dxayG!tT?Y+Sie6Wth77cPt@Ze1B;jOPq$FuE|VZ8Klb{O7+jcmA2)xqbsK zTmw&&+wEldd6rezG9~VLN_~(p8+;1^>P0-oYYzH5Wk`rmSt}tT3bV&k_n?{YC3p#{ zc$=--TdAxUX?dBZ8YqyH5{lZ^S(q?Kaw-6#;!SP=beqY+X;6C5DSC4KBAD;L|(Yfew=((4&qk0;d>%U z1$Sx0_L8|~V(BD6ua(o~!foI>P5xO2PcJ$tVgFIB7lzC`#l7GBCBvl!rnWh^`Bb%_*aiB0) z5+pIfL zLHlMbKg;51O*6hCUf0z3HBgUK-bAoo3;U=#NH|0=2r< z7$(FCBLsSO_+`Qs!d1dGhKnY@j%C6T<=xQ;*AMd>V!E~^7;=W3iydD4`W*oYoL=rn PTgc8mH1MV= 0; k--) { + index += (remainder % shape[k < axis ? k : k + 1]) * strides[k < axis ? k : k + 1]; + remainder /= shape[k < axis ? k : k + 1]; + } + index += i * axis_stride; - int offset = outer_index * strides[0] + inner_index; - - for (int i = 0; i < strides[target_axis]; ++i) { - int index = offset + i * strides[target_axis + 1]; - //atomicAdd(&result_data[outer_index * inner_size + inner_index], data[index]); + atomicAdd(&result_data[tid], data[index]); } } } @@ -184,20 +186,30 @@ __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis) { cudaDeviceSynchronize(); } else { + int axis_stride = tensor->strides[axis]; - int target_axis_stride = tensor->strides[axis]; - int inner_size = tensor->strides[axis + 1]; - int outer_size = tensor->size / target_axis_stride; + // Calculate the size of the resulting tensor + int result_size = 1; + for (int i = 0; i < tensor->ndim; i++) { + if (i != axis) { + result_size *= tensor->shape[i]; + } + } + // Allocate memory for strides and shape on the device int* d_strides; - cudaMalloc(&d_strides, (tensor->ndim + 1) * sizeof(int)); - cudaMemcpy(d_strides, tensor->strides, (tensor->ndim + 1) * sizeof(int), cudaMemcpyHostToDevice); + int* d_shape; + cudaMalloc(&d_strides, tensor->ndim * sizeof(int)); + cudaMalloc(&d_shape, tensor->ndim * sizeof(int)); + cudaMemcpy(d_strides, tensor->strides, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + cudaMemcpy(d_shape, tensor->shape, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); - cudaMemset(result_data, 0, outer_size * sizeof(float)); + // Initialize result_data to 0 + cudaMemset(result_data, 0, result_size * sizeof(float)); - int num_threads = outer_size; + int num_threads = result_size; int num_blocks = (num_threads + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - sum_tensor_cuda_kernel_axis<<>>(tensor->data, result_data, d_strides, axis, inner_size, outer_size); + sum_tensor_cuda_kernel_axis<<>>(tensor->data, result_data, d_strides, d_shape, axis, tensor->ndim, axis_stride, tensor->size, result_size); cudaError_t error = cudaGetLastError(); if (error != cudaSuccess) { @@ -209,6 +221,7 @@ __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis) { // Free allocated memory cudaFree(d_strides); + cudaFree(d_shape); } } diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index 822d661..2ba86e8 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -14,7 +14,7 @@ __host__ void sub_broadcasted_tensor_cuda(Tensor* tensor1, Tensor* tensor2, float* result_data, int* broadcasted_shape, int broadcasted_size); __global__ void sum_tensor_cuda_kernel(float* data, float* result_data); - __global__ void sum_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int target_axis, int inner_size, int outer_size); + __global__ void sum_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size); __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis); __global__ void sub_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size); diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 129a747..41403f0 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -202,9 +202,9 @@ extern "C" { ndim = tensor->ndim - 1; } - int size = 1; + int axis_size = 1; for (int i = 0; i < ndim; i++) { - size *= shape[i]; + axis_size *= shape[i]; } if (strcmp(tensor->device, "cuda") == 0) { @@ -213,11 +213,7 @@ extern "C" { if (axis == -1) { cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); } else { - - int target_axis_stride = tensor->strides[axis]; - int outer_size = tensor->size / target_axis_stride; - - cudaMalloc((void**)&result_data, outer_size * sizeof(float)); + cudaMalloc((void**)&result_data, axis_size * sizeof(float)); } sum_tensor_cuda(tensor, result_data, axis); @@ -241,13 +237,13 @@ extern "C" { return create_tensor(result_data, shape, ndim, device); } else { - float* result_data = (float*)calloc(size, sizeof(float)); + float* result_data = (float*)calloc(axis_size, sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } - sum_tensor_cpu(tensor, result_data, size, shape, axis); + sum_tensor_cpu(tensor, result_data, axis_size, shape, axis); if (keepdim) { if (axis == -1){ diff --git a/norch/libtensor.so b/norch/libtensor.so index eb4a5ac351498ca289360457d4a81cd30f5d8342..e70bc773b98d54d2f61b5b4a51328a7791f920f9 100755 GIT binary patch delta 48919 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
YPE5sT z!5hA1E*G#OPjS`B2>L$80$Hc6mfJ~6JqnGbovb0#e?v6FedzJWcCsy#8_i`!H3~dE zs(WXafsen=iZYF#(UH~KS-g?Cd+$KSM(9^Q&Rk||8}p#r*M}Prk8#qJjwF|Q1@%5y z!S!VG_e|t=W)9+N;(#WYHTTe2u>|6G(J#52)!-LyvN@U5ZQzqynakqX3trR0d=Y2r z3vdHZUkpC9uj^Jn)%0g3t01tyD9an>5mr(0Cs-sSw+g)TF1{k^@;304p3H5`!ltv} zsb~paQ}yh}BhwyW#X?qBxy*wq8AB%Pc5dU~DEhjR{W*0DD&KvCYi&j4R`Aee2Bql4 zCGfbN%-uT
3Jg@afOTX(QjwpJQ(d&kQ;#yp2J3JP)8r*|-rWjY7^g{PQ{52ye? zc!0V1jCIWCsXx5N0%^Dj6`pdx6Ziky)?x6A>sjBuO{3y9@VcYS`{A+^P4O67obcWwcS(8kFnk- zoT(J>{g|wOfahE8_I)ulHowOrS=Ke8;d|c1->Z{SUWMY*`&jW?bg9J7W8Pj!$rWmEcdzc*rQkK$VDG4K?3-=ok2_>15J6q}RHxeNU4Z&^`h z^Fzz+b>k9Jha6Q8 zz6tj_*@_>5{|1UOah>4Bo7s-6+Z&F%Q%_3lKs%Jz3gv@1 z!b?M~;IBluw#@Sx@B*wTxxnO9ZuE&J)|U}Y18>K1K=ezPht&)GEUaXvx1ho!U$G%s z8Gi-W|79*yc>%obBJ&4%;8iRI&+SAV!4b)ZB5kU4oXd0*DfCB|)`{wW7>ns9@Q1MJ z#P79&Z-O@w(*p-_lR5unJK~3@n!`WTNmHvKo_>sz3|=3lH|f-5-U z%=xZ!*29#JqwV%N{7UdyR(7xVsYqWLC9!X=%Vw+yaStaQXRSk=sg2;t*sL|+zX#82 zXCRYtig?KFlN->Oh~uG*#q7b{(vxjm^8wCOttlQ)-EDxlVl8u7$IUGM1mbI@EI#k! z{4*!+5jBL2+vZFA+Y-(4*~P5jz5znT4Db^Rn19Wg8V26*1p~Ps%mxp@Ez1DZm`M}J z@2rOSiEQr3NSJ#Kd?_BNWOaWIz7h`xas?rc0_+ZaW|f&bQny4#GC{tjTb59Rcijc5qXXAp#)PsN5?ll znK8s)Rn^##d3WU1IeNK{{ODnw-YZg3rU%o1v^P(e>*3K7L%p7Bc9-kXQ4%|?G` Date: Thu, 23 May 2024 01:26:28 -0300 Subject: [PATCH 03/14] max cuda and max cuda axis --- build/cuda.cu.o | Bin 172544 -> 188272 bytes build/tensor.o | Bin 52416 -> 52872 bytes norch/csrc/cuda.cu | 123 ++++++++++++++++++++++++++++++++++++++++++ norch/csrc/cuda.h | 4 ++ norch/csrc/tensor.cpp | 50 ++++++++++++----- norch/libtensor.so | Bin 224680 -> 241688 bytes 6 files changed, 163 insertions(+), 14 deletions(-) diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 1c85a787038c01f348bb054e0e6c5c7a6c0c1191..b13342830055303317af7e2ca737ea27fec38071 100644 GIT binary patch delta 38043 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 H#f$zQQ2sBL delta 32909 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 literal 52416 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 diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index d38187b..9150d60 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -2,6 +2,7 @@ #include #include #include +#include #define THREADS_PER_BLOCK 128 #define TILE_SIZE 32 @@ -225,6 +226,128 @@ __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis) { } } +__global__ void max_tensor_cuda_kernel(float* data, float* result_data, int size) { + __shared__ float partial_sum[THREADS_PER_BLOCK * sizeof(float)]; + + int tid = threadIdx.x; + int i = blockIdx.x * blockDim.x + threadIdx.x; + + partial_sum[tid] = (i < size) ? data[i] : 0; + + __syncthreads(); + + // Perform block-wise reduction + for (int s = blockDim.x / 2; s > 0; s >>= 1) { + if (tid < s) { + partial_sum[tid] = fmax(partial_sum[tid], partial_sum[tid + s]); + } + __syncthreads(); + } + + // Write block sum to global memory + if (tid == 0) { + result_data[blockIdx.x] = partial_sum[0]; + } +} + +__device__ float atomicMaxFloat(float* address, float val) { + int* address_as_int = (int*)address; + int old = *address_as_int, assumed; + + do { + assumed = old; + old = atomicCAS(address_as_int, assumed, + __float_as_int(fmaxf(val, __int_as_float(assumed)))); + } while (assumed != old); + + return __int_as_float(old); +} + +__global__ void max_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size) { + int tid = blockIdx.x * blockDim.x + threadIdx.x; + + if (tid < result_size) { + for (int i = 0; i < shape[axis]; i++) { + int index = 0; + int remainder = tid; + for (int k = ndim - 2; k >= 0; k--) { + index += (remainder % shape[k < axis ? k : k + 1]) * strides[k < axis ? k : k + 1]; + remainder /= shape[k < axis ? k : k + 1]; + } + index += i * axis_stride; + + atomicMaxFloat(&result_data[tid], data[index]); + } + } +} + +__host__ void max_tensor_cuda(Tensor* tensor, float* result_data, int axis) { + + if (axis == -1) { + cudaMemcpy(result_data, tensor->data, tensor->size * sizeof(float), cudaMemcpyHostToDevice); + + int num_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + + // First-level reduction + max_tensor_cuda_kernel<<>>(tensor->data, result_data, tensor->size); + + // If necessary, perform multiple levels of reduction + while (num_blocks > 1) { + int num_blocks_next = (num_blocks + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + max_tensor_cuda_kernel<<>>(result_data, result_data, num_blocks); + num_blocks = num_blocks_next; + } + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); + + } else { + int axis_stride = tensor->strides[axis]; + + // Calculate the size of the resulting tensor + int result_size = 1; + for (int i = 0; i < tensor->ndim; i++) { + if (i != axis) { + result_size *= tensor->shape[i]; + } + } + + // Allocate memory for strides and shape on the device + int* d_strides; + int* d_shape; + cudaMalloc(&d_strides, tensor->ndim * sizeof(int)); + cudaMalloc(&d_shape, tensor->ndim * sizeof(int)); + cudaMemcpy(d_strides, tensor->strides, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + cudaMemcpy(d_shape, tensor->shape, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + + // Initialize result_data to 0 + float neg_inf = -FLT_MAX; + cudaMemset(result_data, *reinterpret_cast(&neg_inf), result_size * sizeof(float)); + cudaMemset(result_data, 0, result_size * sizeof(float)); + + int num_threads = result_size; + int num_blocks = (num_threads + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + max_tensor_cuda_kernel_axis<<>>(tensor->data, result_data, d_strides, d_shape, axis, tensor->ndim, axis_stride, tensor->size, result_size); + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); + + // Free allocated memory + cudaFree(d_strides); + cudaFree(d_shape); + } +} + __global__ void sub_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size) { int i = blockIdx.x * blockDim.x + threadIdx.x; diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index 2ba86e8..b0ccbf2 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -17,6 +17,10 @@ __global__ void sum_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size); __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis); + __global__ void max_tensor_cuda_kernel(float* data, float* result_data); + __global__ void max_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size); + __host__ void max_tensor_cuda(Tensor* tensor, float* result_data, int axis); + __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.cpp b/norch/csrc/tensor.cpp index 41403f0..d94a3da 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -290,26 +290,20 @@ extern "C" { ndim = tensor->ndim - 1; } - int size = 1; + int axis_size = 1; for (int i = 0; i < ndim; i++) { - size *= shape[i]; + axis_size *= shape[i]; } if (strcmp(tensor->device, "cuda") == 0) { float* result_data; - cudaMalloc((void**)&result_data, size * sizeof(float)); - //cudaMemset(result_data, -INFINITY, size * sizeof(float)); - //max_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { - float* result_data = (float*)malloc(size * sizeof(float)); - if (result_data == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); + if (axis == -1) { + cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); + } else { + cudaMalloc((void**)&result_data, axis_size * sizeof(float)); } - max_tensor_cpu(tensor, result_data, size, shape, axis); + max_tensor_cuda(tensor, result_data, axis); if (keepdim) { if (axis == -1){ @@ -325,9 +319,37 @@ extern "C" { } shape[axis] = 1; ndim = tensor->ndim; - } + } + } + return create_tensor(result_data, shape, ndim, device); + } + else { + float* result_data = (float*)malloc(axis_size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + max_tensor_cpu(tensor, result_data, axis_size, shape, axis); + + if (keepdim) { + if (axis == -1){ + ndim = tensor->ndim; + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = 1; + } + } else { + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = tensor->shape[i]; + } + shape[axis] = 1; + ndim = tensor->ndim; + } + + } return create_tensor(result_data, shape, ndim, device); } } diff --git a/norch/libtensor.so b/norch/libtensor.so index e70bc773b98d54d2f61b5b4a51328a7791f920f9..57fb5bb9b835ca30e639489baee6b0b2f6e9f67b 100755 GIT binary patch delta 54469 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 delta 48765 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 LhKqjxCiedU%MA!l From e2a0262c4e0658282f2815f1b0d92b5556a9f5ca Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 01:29:23 -0300 Subject: [PATCH 04/14] small fix max cuda axis was setting init to 0 instead of -inf --- norch/csrc/cuda.cu | 1 - 1 file changed, 1 deletion(-) diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 9150d60..fdaaba5 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -328,7 +328,6 @@ __host__ void max_tensor_cuda(Tensor* tensor, float* result_data, int axis) { // Initialize result_data to 0 float neg_inf = -FLT_MAX; cudaMemset(result_data, *reinterpret_cast(&neg_inf), result_size * sizeof(float)); - cudaMemset(result_data, 0, result_size * sizeof(float)); int num_threads = result_size; int num_blocks = (num_threads + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; From 223229fcd352e41ce6fd195f19fe25cbf0816cf7 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 01:35:45 -0300 Subject: [PATCH 05/14] min cuda and min cuda axis --- norch/csrc/cuda.cu | 131 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 4 deletions(-) diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index fdaaba5..7c193fa 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -227,26 +227,26 @@ __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis) { } __global__ void max_tensor_cuda_kernel(float* data, float* result_data, int size) { - __shared__ float partial_sum[THREADS_PER_BLOCK * sizeof(float)]; + __shared__ float partial_max[THREADS_PER_BLOCK * sizeof(float)]; int tid = threadIdx.x; int i = blockIdx.x * blockDim.x + threadIdx.x; - partial_sum[tid] = (i < size) ? data[i] : 0; + partial_max[tid] = (i < size) ? data[i] : -FLT_MAX; __syncthreads(); // Perform block-wise reduction for (int s = blockDim.x / 2; s > 0; s >>= 1) { if (tid < s) { - partial_sum[tid] = fmax(partial_sum[tid], partial_sum[tid + s]); + partial_max[tid] = fmax(partial_max[tid], partial_max[tid + s]); } __syncthreads(); } // Write block sum to global memory if (tid == 0) { - result_data[blockIdx.x] = partial_sum[0]; + result_data[blockIdx.x] = partial_max[0]; } } @@ -347,6 +347,129 @@ __host__ void max_tensor_cuda(Tensor* tensor, float* result_data, int axis) { } } +__global__ void min_tensor_cuda_kernel(float* data, float* result_data, int size) { + __shared__ float partial_min[THREADS_PER_BLOCK * sizeof(float)]; + + int tid = threadIdx.x; + int i = blockIdx.x * blockDim.x + threadIdx.x; + + partial_min[tid] = (i < size) ? data[i] : FLT_MAX; + + __syncthreads(); + + // Perform block-wise reduction + for (int s = blockDim.x / 2; s > 0; s >>= 1) { + if (tid < s) { + partial_min[tid] = fmin(partial_min[tid], partial_min[tid + s]); + } + __syncthreads(); + } + + // Write block sum to global memory + if (tid == 0) { + result_data[blockIdx.x] = partial_min[0]; + } +} + +__device__ float atomicMinFloat(float* address, float val) { + int* address_as_int = (int*)address; + int old = *address_as_int, assumed; + + do { + assumed = old; + old = atomicCAS(address_as_int, assumed, + __float_as_int(fminf(val, __int_as_float(assumed)))); + } while (assumed != old); + + return __int_as_float(old); +} + +__global__ void min_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size) { + int tid = blockIdx.x * blockDim.x + threadIdx.x; + + if (tid < result_size) { + for (int i = 0; i < shape[axis]; i++) { + int index = 0; + int remainder = tid; + for (int k = ndim - 2; k >= 0; k--) { + index += (remainder % shape[k < axis ? k : k + 1]) * strides[k < axis ? k : k + 1]; + remainder /= shape[k < axis ? k : k + 1]; + } + index += i * axis_stride; + + atomicMinFloat(&result_data[tid], data[index]); + } + } +} + +__host__ void min_tensor_cuda(Tensor* tensor, float* result_data, int axis) { + + if (axis == -1) { + cudaMemcpy(result_data, tensor->data, tensor->size * sizeof(float), cudaMemcpyHostToDevice); + + int num_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + + // First-level reduction + min_tensor_cuda_kernel<<>>(tensor->data, result_data, tensor->size); + + // If necessary, perform multiple levels of reduction + while (num_blocks > 1) { + int num_blocks_next = (num_blocks + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + min_tensor_cuda_kernel<<>>(result_data, result_data, num_blocks); + num_blocks = num_blocks_next; + } + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); + + } else { + int axis_stride = tensor->strides[axis]; + + // Calculate the size of the resulting tensor + int result_size = 1; + for (int i = 0; i < tensor->ndim; i++) { + if (i != axis) { + result_size *= tensor->shape[i]; + } + } + + // Allocate memory for strides and shape on the device + int* d_strides; + int* d_shape; + cudaMalloc(&d_strides, tensor->ndim * sizeof(int)); + cudaMalloc(&d_shape, tensor->ndim * sizeof(int)); + cudaMemcpy(d_strides, tensor->strides, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + cudaMemcpy(d_shape, tensor->shape, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + + // Initialize result_data to 0 + float inf = FLT_MAX; + cudaMemset(result_data, *reinterpret_cast(&inf), result_size * sizeof(float)); + + int num_threads = result_size; + int num_blocks = (num_threads + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + min_tensor_cuda_kernel_axis<<>>(tensor->data, result_data, d_strides, d_shape, axis, tensor->ndim, axis_stride, tensor->size, result_size); + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); + + // Free allocated memory + cudaFree(d_strides); + cudaFree(d_shape); + } +} + + + __global__ void sub_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size) { int i = blockIdx.x * blockDim.x + threadIdx.x; From 9708054ecde1c1c0cfe6be635c2ce471c3d0d5ce Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 01:36:04 -0300 Subject: [PATCH 06/14] min cuda and min cuda axis --- build/cuda.cu.o | Bin 188272 -> 203032 bytes norch/libtensor.so | Bin 241688 -> 250496 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/build/cuda.cu.o b/build/cuda.cu.o index b13342830055303317af7e2ca737ea27fec38071..23217f653b003eaca8b8aa1e56ca8c57bafc7ee6 100644 GIT binary patch delta 38125 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 delta 34207 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 bbcy(KrXl^F!e0Q>h;#27=dr5(zw7=##{6hk diff --git a/norch/libtensor.so b/norch/libtensor.so index 57fb5bb9b835ca30e639489baee6b0b2f6e9f67b..0f5fce8d116a2aedf968b0000f094fb310b2e5c9 100755 GIT binary patch delta 46990 zcmcG1cU%-#)b`w&U0B*KEW0dyLFt09OIuVFR1_5zJ66C7Ry1PQ#TE-<$*6-y6O*X1 z#vV0^EyWUzl44?w*dj)aC7P%a_dECA861cA{l34x>u=`V^PF? z2vD`?ZCU0_{dV$R$fU0ky=p|SnnipQbT(AemljgW95pSR!$-57L;p951X`F$;8(FN z3`u>yz7Y6b%Z{f`{K?oH#Riz_t_BDy0(=ocu%gO>Zg6}SM#Y{xYttlSnEYK zOq6FyMwzNrA(P9G;>`BOz?ndK8H*^fNQ5H^jubeWz=2a!Dwt*<)8S|?>R4pJ(F$iE zwWfk;3o;vycB0-MWDXpi;OGiRcZT7+X}nw@%k+XHkI!UH_TG@|14myt`oYm3j(j)@ z;Sk4>84CGfa1_Ha5{^-DjDceu9Phv}9*&7{;4}%2sU*iR(?Cv#V+I^E;g|)-9608} zAtt^9>tcTwl=%`O%7q{+;8+3&FJj96PQM|J_g5tVmoMDw<|Mq`T#{lrdX*n!pzy~sZ8I(Yp`{PC8ET6ZD%XGA&=%ly( z=ebhc`#h}}k2FrRp~0B=bN(ZDQ{e`29AarNUi-=#M}82+)kD%rdlr=jAAEBojcu$R-_Zxh%`z$T8f(^DS@=n{49o7 zv6lvrD0WA!I2gOqs6VaWjbT>6)`|P?7d}*LvhNhfToUQi@X~}N(Wi=&EFQ5&t=v;>jYuMI7#l$0&d= z1`K0om`HJ4qrZ_G;3@$XX!eIu%TDq*rOwVp?J1f|Ce|`1EIjxOj?mN zpnr=~cny!dO@8ymjj1{G4^Cs?z%)Pe7H^Y1cQOGPY1e+}MXg=+v`*=gXcp@nu%7x$ zjoT+~7PG|R!}mHkjTJj(ZgW~s0)?4%ATj&F!35w>czfAbGSo-9Y(5nyq^r0mNNazQ zI3?UQ)L&YfyTy@7jiWdn8HS02DT%qJjHTqW#U3~y#(0>ns6KUj!dY=-)Z*4DO^Iz# zFRn=a1+7Thx;u(XaGw~YGyp@zwSSi1WiZ+OU(r(1etby`V}gU?;__l9iOsDorFb`S z{HKZRepe_ib<+)TMfDc1XVOG%FHT@j3+av+Mp|kK;#T!*0_`Vh;+=$k!Qp+wk2RX? zKYmMT7E>qYiMZU4*HAoy3MNb(rQza&mTIdKXG(}TU2{bL24ZuYi2We73U5=Gz4cJy z7*jVDBgN6sh<9hw6uK-H_?kyPCVK;MqDt0Z#l8=pO?jou?{KkM%c>~8MC{$R;`Shj zH%U@2x`>nHdw1Fo65dqYfBZWT+|Edo|4r`fs-KQ4F1MyJYf24t^ z5qoa#-)|FN5{a+xpt!W7=i?r-!^lk*uUHbnUNN%m;=UwB)>54K176dLq#pW6+$g&( zr}$Um&_sxPOYavHFBAitC^qQPujGOXn+>%yUyB#}^XU`?tp)4?Xlhq_yH&I2A){Xirdv`3oeT+tHUOP$l98VoxyQ zkVygjBKBNnD_W1#bAq@OY~o(gO|0h;D^~O=kNix2VJ@_o)Uof2bAB#w0c%n1 zJ|xl8KE;nAk5xjTy}1#SVIVckhk)UP;9sH4{_~Cz&|GKc(>goLl!$gbBJ-B5go)$C z>=v<7|6-VtD&|m~KVrIwwh-`daQSaLY`q)-K?gdPnJ+qE-B4T%{ibG4y;UJwSE2Oa z2ZocRodc=7AU^7m@OJI#_*X0Nl7V!ZGM>xn(vk{DdXxf>>MPDa1zsTP84A3*KlQI! zOzVg4dFy%2BfHGdiZ-5{pUd!mGMo{&XI#;E8LpAx%VfBx4DTVseMQ`kE5dg^QVNk3 zkhTMCi<05eCs2$h$Z%Yjlx#A5umpn4kl~rqHi7NgGJ|+KL5k(d@Kpq%r#u<{i3~50 z;T9QQB*SOb;V}LsGK2KQ2-_#g@a(z*3{xh<#py$=^JRFt%zvp27k33>t;9I40CyW) zlIqerS%LUE6dp;*@B$gWQ-&Xu;Rj^+=Q8}L47azC8BWR!4PWVXXa_!$8Kj*QmwPV5x5+B<6_*)aTtRYtDP3l;MU%&yk|{)nca}hqQA_P_ z3Urkj5@ZGF3Z_Pz4DT-U&yeBb9z?9!GMtt9=Snz^f1k{dCm8@cBEt)0IBhaD7Rm74 zGXD}8zC?yklHr2@r~MC^GMS-RR$#si=Vka(87^KoiM3LOFO~VPli_>b;C5z{%<$eD z1G7_xua)5kWH?-n>e5jezOoKwn3FQRT!vQ>9OB251s_tnASGaOpkma zbpL_zM>6~v2E_DShWD@Qe{5X#W->}24lt~d;i(u9lcx+XkwB2XGQ6z}50T;0-3;N6 zk{P5cATF06!`I6yvdM6`z}KY=87@BkAhv87zNpR{?l+ckG=ALug3OR7D*!iRb*Vsx zH?2b%rbvdv9ZX#+k>PoDC~WO@IPiZZGnCaC7-oPBpD)8l$?&BzT>6BM&6P6TUFN?| zhIhocH2#}phT*aTJ7qZB3e}|pG92!)>(Wsf-lz_RRUpHyGTdGzGwhHVF351546l~q zBV~Av4BsrnAIb1U8UCE&cCz%|l^K}#-mC)gV+OHmWVlV{?Hm789?UA@X0c~K!$tE@FE$$ zQHGbuaDxn=1UQ+0c=wGJJ##Un;{l$nZ)TZj|Bc-r)APUhr*tW2k#^ zh|BGi;YqTJ4#@Br8GclT!}IUDbW(=HBPvMZ`m2%|{Oa5p=7J3Om*Lei{HP4Ck>Lwu z_#+wKQ-(jc%M2gN3=IEf70i_38X5kP4EL1b-^p-a89rKuhlscxk9~m55G5-xTZSjd z@K0s9O@^n*@C+FqD8sX5_~E+#2Zvml;T>6lJQ*G=!wY1%S%w$M@DLeZBEv)La2Wqd zGK2WegP6-?_<_0t@J3pOFP7m;W%yPZUMa&T$nbR-$MX*lK|`5gldM3P4Bsikr^xUF zGCW*{AC=(|GW?_rw|9^ks$_!J?lW%wo;UL(T`W%wf*K8NBhiFhtE^pO={ z#QS{QL(wu^Bf}H+%xpcv<-J_DkYg=4CVTGD@vNgNd-k`QZ%6@0@(qBWIKpqX*wZNY zqO-kdI^a+4dOdeImj0~^ep!UC+fVKyNe9%R%DD<@oeT7W7 z;|eQe0M_R!^yvz{RH2Vj=tC5Ge}&%Tjcz9qb$kO5JxigdEA(WA9;eX56?%|DH`eKP z+NEy*s(aKqP+hIiYm?s|l4lBCX;cd&^_!5K&{Yg6W?y&Gll*@q2E^MR~7nsg>L^r0eq*>4=MD0 z3Vpjm-=NUfD)bd^>-O-9w}J4v3VpglFIDKH6#5W_-d~~jcuTiC!aKeNIKs0Odb&bS zR_JjGJzSv&DRiS;x5MSuLk@thR_L`>#T-!R4;1=sg??3`pO@+6`u~Frz}Nrp6#5~B zzE7cVSLhoQ`dWp);*CzP{}pcla{ZsH(5EZ(QiVQBp$}2${S|tTI$gZ}cdP^G^*&3X zrz`Yig&wES!xegvLN`i!j(GL+kbvxpbU(;vSE%(^q&**R%q~}d7Dw+TT^!Xqa~Zyq z{6>`Ef7gQjlW$n~D}@2<+&KP4VNlF@0GZN8J+fz~Z;6F$_JZ5v-LuQnX8>N~_m9I- zGuYv999M6*@EHTcT$bWG7M!Rl<3|llV;9HrUc-#+wfp>$flW|D{^h_V_Vo)sVUQnt zuMsw(W_;nGch~}=u)FT@4+cG8ul&hh8N3+f@FRx!qZIz#Az{di-#WyfeSDWcF=UXN zYcz0_yH`@c_1IIH`CM?=^gr-_$T_TyX3Q{OIa1f)n)i z-rM|7!z)lPzFXJa70VMHr7ry(i3_PvoS&^&(S$T(B+Bi!1oP30L;X<6&1 z^|}`aZSU8BG+_G;{_)5FZBzr=_#W$_6R=u6qv0?CI+rrQHbEmLTHu-_=h( z8H`Q;r<_>(<@r}^AJu}94MbQ60md1HCzVlX1k$%K+ z(w^`M2%)8X290Tn# zX}r7hFQ)WEg?!Jcjo9+v$#}27M#g)`)M&P!H)-DXpZUjAx4Kp8rFISFKblQElwHQV+hf`BSNO*p{rGP7 zLiaMA#PREo{84)c_vkv{-*ddFES#;r#5XUCWxu{cqMuu4VBgo`x_s}Sh3HRIOVO{r zN}?Z4jO>xK{I#-qUS~bt4u1weab`c)n?K+cexfGyDxW{K0rGfnR!{bKchbOke)Ozx z_TmM;%MK&IWmX3i$^SDej&-?2*qhHbus7TYd*T^j*ZwZC-?~KD_Yos<;)U4-?2*&_ zi`g;k-SfO|l`pHiNV>WEoM?8xE8)`cE9OM8=YAzzzs%{t)}H4>=fO#pZu9LXB9EBe}2pFT{zF{ z1^4#o_U3cS`ynmAxx5i;J4+__k3W#^U>8NRE*!2H_2FAB3TF*fq^b5r75XTa)RMX2 z1>F*>zT<-{I=G!iQUt5`@f8th7XN-l92(4@s%XMm5NYGAW6;L_&@$S_#46H86)~b7 zd$JdMAoiMrpE=uz68KR|f>119z9bS_uxCkEHl7+_H7&j3)ATh;n$94+FPEsH~=`6J63vF&Sd?Y{3Hf`&{uCp9GJ3~5LZ zF@k6OdmGq-SJ;!?^%ei%y+C&RSG*e^!CpSjKU`_#v-xK1&i_a|5x<5HXHOsJ?ShfN zz>ji!_)?-z=5v>i@|sBXy52JLXP4)=``3BZe8ESo2uDBiIV?CRFKw@O~9OUn<*ubuTPMZ4c0Ka)GV_0}^g+J7 zT4>5X{g<>gi_a6nQ44;CP>9m`Y9Wp_e@A9@RHcD^{tw}62M+~n!cIwiFTW#vr-=~- z@-r(7T+hSnbvz5bkMn3w1J-erEZ5t|$i!*BDw_S_8KDd2?W>~LXJ3ACbxqf`t)du$LQ^IM6cfvI?A=m*2KJpWV8b_jo^sJr9?KcYWEu zhY4BH`_b$tf8#pXr+fGbU0o zw-VjfV}x!RF|t4G=6_t1kKW}iYa1DMeuYgvF2H5>WcGqzanOhOlC>?^xsM6yue8fhz)j zwR_7!6Z&~GBHBzrjO_A zSKKFc)!q1<-^K6xxG%e98?XH&hW+Jpyj!3{eC{VL*bVncZ~U{B-}K2=_v?R3jo7i3 z&tKo4o%AO$pW4EoU;nA!fxFbKxDGzv!mrp+ftK?PH%6kb`3@Tk*abDD+@($Yw;LO= z5B9({Fdv=ayL=kQezuQ9wCYm>JMRvO=mI>Zui0}@ifF;-q{I6VBfIre{_juoT?c~? z9>b5}KgxX804?V2o4T@t{va%SH}ZdO3Spn@BApw$xeeOK7j2GX1^Dj_a1*g}vw?;bgesO8(R4m!TLIh%&)n9?P_Vro)pq{q zwiayi4Z;FLx_t(|Z`>Zo7VjW5zi&67mb_)LkBR>XSVr%WSX%ESEJkcYL;2Lt3Scj( z{Hzg7zi&V5$_7`H8prUBcZ5P4a(DDYCH(dsactM^q~2#c3~Zxo#Ag~Gy3@$M{+%eD z`A$0vkcQu}vk|iLmv?q$ov9&@&)PKu_2$3b6^EMgPj)qC4Oejq-y!fth?)%OL^?@* zwvl$-xk9S5@k4f(u-Dh{zwM4N>OQRt|A4qo?{DPwd(zq4m-$_5efVK}n)+ixN=YO;Sx8undJ;aUc=PH?b&&1E@B-E_|((s?19Dnu^+P01pdhB z2JTt#(v3PjuGsV7bQ{FJSj3l|i{=OX(11NK4;O$DI{HI9Hhvy|^mM5EOL+B63v4VW z1t2#2xp^>&oU695vk#M=ZN2AI)h?F(dL}>ZXFJN=^XlgZEc%B3^H)22b2>lbH-C2j zbbj7%!SG39<8RH_K3ECj(SY_=9H;_*9s^VES|D@8{VI)P7&` z&n{%3-}sb^O}y?;#cL5ha+JdXYjO=g^I{yD!SA@Zz$=>C#BwKUe&O3)iVOXG7VhM% zn(Xq7gzN>!;j_{$crQf5X>W)38~oXqc_@y5bjg=B*m-m_f={>{?)=*{_+OVio>xW>#Nz*zhcHmm1lhg z-7;?mu#jN2O+*>tTH6jS{weBAv%-g-Mv`%XL z0&uz8m;d1UO!oUhB*ra+AjT;E&>vQGihuM+IDE!Px|0;})42a7*n{J6lTaqVf+rB$o!YKU;1}Qa&6zd&?T)uX&nPC+IXw1c zBJ~_0h59~p4efX@=$o2X;6ghdw*8PBX4HnyxDm|;yu%;)Bg*wL)cLp0Q(ZiUfBZ)n z`^{)P;Q~fu=KpEJ^%zYWe|0>+^-fEByHUVC``eHj&ysqBupNe7vpV-?Kz77>vaOFD#kk#d#{Lu@y-~& z(2>&d-cTUMJJfE7XF=B9+0*xuQ1$|UXNZo5^6MZelz<{Blw}Z9%{1&nu9VQ+Q8+B8 zuK}uA%V#|4%N`p>I&RZ2!k93cbX*5uta-P%UdJ`W!%sSH3w&Rc?vf9|mk#le5l||Z zFgSko-Ni4hSn;^2SKwb&HO@%=7%8? zO)EUAjYpF4DZ>HwE#_+<_GM=bArwP~5Q+yQ_=Fc>>GLo}%VG5>u0bV~VrYRxu@!u2 zB%u&`jr#~fF#t!ER#X>Bzrlp2)nGz%dN_$BYalpH4OBEf?_T7AEgKzAW;-Ub7&;j@JN1N zL?{ArRR0d)3;*88o+}i7U{M6ytBAKejqSR*08HzlVT#H#p@p>all`R1J)j}9^4ZXu zn$h606z11kTjS=zyyrie{G+F1+0p{aR6CR}e-_`Z5GK`buou z@+Gzgcqly}o_cKAgMe)pYs{xiYlje~e*HzJn-H9WsSN6(OwRDl4e@dhEu(RLjYo4k zxYT2+DXg0ZZUe|5J?T#dY06+S59aiRlINhw3ciuhwUqDgJc-W+?W263;h|kMhz!y_ z@T@srKxXvaeuSc`AEC$_L}qkLOtBr>s-S2OjiwYo!na*$NIv}}ibZ&UCk`YOr*L@d z^Z8@54DU_$<#*P^uxI)bragTLQ`3Pf)**BH%iiF(0$QnHvO;qy(?R%F7-f3hM`9We z(bwb`5~f`^utfvNq~6(wPzZepg}IPSYS%n)D1}xkDD===O0lYkMDaT`hxS)@h`y#p z0ijri0~^_&?9eWFZYg)@r~SzeJ!mo6q4#x%eR&C#p*!@D{&a_)+KcSa@Af4-bdz3W zhtBRxcIa0<$qwz>m+a67dXgRb!=5CJ$o^!9&hHMycv26AcoaJ{2hq_`7Iu+BIoCr9 zB@6nkCIP#MJM_~&B&-Pl)pY4C8zVGX_)&#?*@7N~xu!1}qZ3`huVt@#9e54urL049 zCDyIbO4@;;cx2uCVkV~ncs`{G%haeBTiBh9QFeDiQPqb~*fB*+&w3Ompb|>ask21E zcatbw@W?*xO@e8IgADCOgE8?-|JDe@Syafnbt4OQ3=cKUJzDAqeQ*-Lqv?2|yvHxu z<)ugQ71jsSKZd3&rpRI-p!CL05`7==r4d#^duzS~mwHS1pB}PKWrMqth}B(5#1(lY z;zhYo_zr}kpqvB!Oex(uN|d=>B+BD3s5QHKk%&1Q{qNo7Oio=0(}P^XRN9L$t?vwe z=b+UJrjgKm%JesU)r~GO8?=fB_Zjp?&8nV+=^hUBcsDuIU!4il`Obu?e^0{Xj+ypD zV--x@q1BY>a(js>1biveO6Y`|nLP;8&p5u%y2_b;?L?Rkbs|hzJqXkCj^OtpG*-dX z3@;LL^YBeOiAmE*Vw!=6xwt!KYV#$IZzZ(#fBg9QY#z%j?f>S3X+`=yKx%$+K=tM7 zYmmp&=F?6B(x4#rc{d?MgUVcfor!UE>O5gt5XxXZx(O|!QMPL<0-vb4-b`2)jp7pA zMSTl=XBw~Qd+ySm=o4t5@-lb0GyVkNE0p;mf3{B-;j9aK;gVWLn0)67Rj$DFN3QTl z4@~Rrv|(Q~Ss4#RqeOLf6D84U=sG2l&`~(%hH}_;xq{9ejd97IK{$$M3uYT|#CH}7 zZNRZ_I_2Qfg!o24GDFnQ*pws&7-A(!bq5?xfDms%dUj?998H4oy%)Od5<891rO%`x z{g*>SS~Zo@ol7Ah4HVVN6eU}APJOm*?QlpT!Vzzjq?ynb9N=?>uqz%FyKI<3=-#!{ z=$dt)(dh|%qQ*0sMt6BKrN0QzdfpzZ&<^$a9<-H3H=~U#x>XYiU7zVRI!!woofCmi z)LgNW=*~@`Y#ZP|BD~G^AiF->!7N#H-P*~cYe_0ne=?Ou*RCy%ZbvDtKgdF(n5^jKQIA&#uG_*7B93jYV;?cNM;RiE#% zFf$k#g>{XPimtVw=5(#OmJqh`QW~6JCLOwoV<_8$7(8?V8KU|*eB1tQve!ar2=ZpX zPp8XkQ48U&3C(qxJDOB`{2dxZP74~ulTozVkZ8JDd@1U8;eo*0^;%lg52Ci|o6SPC zxfwh!I1&LHQ`Shr6+Dh|tx2a`yGKy2l1R!mRn*fWm0UB^>vMH%g1HPr$0*d0U2YS) z1fW?iWuyxA*b>TgrzvH6Fq|@d8BUo#7xg*tt?aj>I@7d1Q>9J#D;lM$9AKjX1r(Ej zz8y_ztW7A*{31%@6h>*fi2AvPN*Ys>`ZPCF-UOstmX5d2^Ng$NZPXoJh$A%rkygfJ}}Hs1Lu!r^e( zczY7~L`}aC!7~CjUbCo&hbRe0rPL=(OT^PJP*@NFzl+wR0SZ=UB*|Dm76ybPqf6Kz zLTxOj)FYB8^|FC9))v8(x{s)9;J+QbJ$$)PsdC>4wA4{Ic6pQl4sg+{i&tdMD zhEnFXR?7Tc0c8#dq|A#&{Z@dIIo4XA`FZ0v%k^w!n39Lk@tm4K$8*&H z%GBAPj^{v8_w`pY72psQdt+?eo4Lcbil&Rn=*AZ(w^%f>H+XSo8F!sgBsPR zijR7;64?L3>7E;vN0=-F=$_jvn(nzPdQqlE-sEyQKvbW?e;Rw6s9AJ7wLX097fudIZY2{_&N# ziaV0H8g!#vp23vs*Br`q%b9Y0DC+n}R^FZ)&w}c69rJ&~)%fcG*yv>+b7tT7l)Y)Y zj|YdmbURVAX$7=uY*Q5ATa1@fg>fJj<;nNpxA*V|o=*aVW6e;gZyvRFq1Kn8b+~A4 zL9I4wEf%d7(HcRmW@_~mtd~Qfs_uJtA6F)LM(zVtMj}_Ow;+iq^j|Tw%OV zt>@cOYe&&~gIX_B>o20!AX@KID{(4M9wAyU`_Wcipw=I0+0~-;W6^qqTJdj$L8~T< z)?(568MS^&tyS5yRSBYXEw!$s)_+CozrK`rJ+%_2^5mhS^{{AtpIVpGvgbwXT+zCa zT4z&hplHnztuv{03bo#AOIzhFT1%+4m|6#lWiOd%tMIQlK|kkFYnoX0BhlK4TH8|V zQqfu@TC=FNIkoCUYrJS}O|4|FEl=LqhPLV-AIh6Zt+BLhx>)v*XpN!PhSWMzEIUWE zdQqz@wVuwRHFprL8frzaCHlKd{LY9N z;dO8Hlg8n&KL@%z$K+wg`7Fa;%v>& zwu#TTbXaACyh2QYI?grHjirL!m|JFjE0IZ|kW&23}`nk@nnj)@Y+U~}7g=4Q|q zj)@jN#OCaJ=7wr)juFmbGdzG)B&`!RHxeA!3{OH8=@~J{3h^t!43A_LDN=(=#|in^ zoTD(pZ<|0ra7<%i2{yx{V@0|}%<;kzY=(!~igX5UmpCRtc!HheU>3lf zt1vRmE4Z=a7^~13o4eFAhrsP6$0Q1NZ0=gme1n(=3OleFf2Zp0bOY{&Ii{O%4V$|$ z;xAD$cpBhz7&gxaVAfTFIhkUz^C;NUIi|bN0-L)t;xFRXmCk}YiUwdFgU#?vQIVd2 znPYkgA7XQly3)BK_xJE46Ai$84x3XIW#Jdz4Y+hq!GX>2cvO)_!RI56=_SOk0<-)V z0;t~{_@u@$c|txm!xLOZ+G4`y-og@WZmKZC|HX$-lN{4WID*acALpQ+FW|QvIHs@g z5Ss_pE4>9i^m0tPU|x+(c6ckRNCAP^++2Y|zy$AK4?j-u!S(Q{AY4z2diWfI!>eYT z$R&hknJ9SRfG-QmG>72u`dg8HCioBq$}q`hTu){_d^N!f-onXZ=^cU#w0z5em7@eN ztcPcWV*gh4@RCr$^?eiw+ge?M35t^wY)pF3ETP5wFd}a@rZRC`TL~MJ-m|SR2AkjP zJY|TM&V!vt@7YfH5SwLNi)fC9TJ)YBgmc&|+dD*ad)OTGo*e}THow^%%3#OAiG|g# z_v|dhuK}}c^~1u%sf`CVcMFit`TxVs(RII_W*%Of$)U5KJ4rX94!4No?H*As8>D z*#3QM(QK`dw-pr#mD|uvA#EGV7ba~-p2A7M*czSC{$n(n&GQs8`yn4;>2?%o9}Z<< zb7fQwH4M(ahS&%Ei-|Y&ugimfT^{_4zz2^q_Q!dgaQ$N5&ZwY3 zodF6A1BY1b1O;#&CtRQ|5B_y|@E;0xi2&zu!v1x6@UP2*KVGX+{X@uK-4F{%ix@Yk zE)NCpt|AdgI}9eM%Y%Pi9{llU7c1=Aj^dHKa2<<=g4bt6%f!M}7z;vJx&!43n?6HP zf@UY=F5p}l&S`d_C=?@Dc7Sh!P)Nna9dL`2w-YR$!l|94vKLfD?*gr%&>IVlumB4u z;ULxSQsK87#rMZ+3HNDdkT~HGa6Sa*A%wa-gn(D5T3rA@)uLE#A^lLXPm?eBuSSp(2`y$u4GAnB-3##3$Ota7C1`$>&G}@fj65B*!ge* z-41_w1b*}A4Zz^-CPanJv_LnI_?KpJ!WEGH2KGjru-*fX5}A%SoNAd4Uu$7Ew!uE?3_Q#u1l|r|P zTP2J8A3H3S0LbHA3je}APPhWBPg3YrGCd#c8F)*9g#8QP*eTNsK@Wi)9Vcub2**-U zhxf@0SwQ%KAx>Dwi>pMY4^^h!a#h*k{h;8F({qw|~BqO+<*>pR|j;!S45Y zpS@`iO%5>GEUdqu(BwLs;@StU3plL{6{dh5C;jOljjUsHz%C9H12ujn9Pb^5cgtQxMs>@zH?2!5ilW($Sp}L4u32Sb!1{djKlP4U+h6^`X zUzZ~B0+c7bz?kn%z>bPou8?*MuspzoggdN3m~#tGl~^sg!)k;Bx7ZNj0x2P0u5yJJ zxPQeD2zj6gJ8PiM<-+7Yz*-4_%eQ#OKw2&w#MlLl72yHV_1V13nV#1J}&SM+y_CbSKz)_ zU>z}2h5}q*Af3|n3M>-u4hm!i3Za1dUnt;$r@qT0(WOL~e3wmS3q}gN@3PI&B*AhI z&#jvBW7w95ZAqm{8@i48ux-->YLl)`jF5?K7qBg361Cw!qd<}{6We_6 zgYB!y6nfLnW7w7lHn<(w^#B4^{ef2(2DS;0G0++V7jWsQ8MO5LH#Pr(YkmN>o#g5Y zx3qP(W7w95ZMK=T+?+Zax&yXKZ2M{!wY_O=CbnGw8-iyy5Am4box}GpaNavt>3j@3 z=V4pIJf#iQU=nQGHeYGW#I_6A7PXMt-gMuYO58IkmP}}l1LEXiC z*jBZe+TL_?CfL;9!zXGaeAEwl8(S|`lm->APIVb9Hqqz8GDR(*;svSh3hPVs$>HnQ zgV&&114~Nusa{^c9=z<-&))cSUrBxHdI40t($rtzYX)ueeS!Ma4Hc+(aS0*s!?#YZ zJYo&TvQ^ZD5kD5E0meK2tEMjUyP12`X+>AlO zTx=@qCz@nkI#~D)Ov9P{`laB47+VIV<;e*zBLJMFzbz>m%S!844HrsHnY=LMKQjuQ z`Xf`Zv}wbN!wEMMu6p(87ULBOHYFV+{!y7SStLdO16_&<)A_`dEv3zq9uQzYxL!3Z z11V2Ue2KrYY=h`83hX~z`0ih}k(cy7f(a1|3b5(=3VzR7(;J&cvXT9%2XvZ72*vwT zU1`Y!9Le5u6(aq=_~3oT%?X^QzgYn6rv#^1H6bmUDE={A0X9GYR zxPO9%o2s&x26)65k1h@HCFc;?c>?5(CNF~M$T^yvqsY0;oLU+XXig~&7>rMpq%@$| z8x#!q;?p?d8jQ1P-YNanIAg>oC(?@2fPr?b(b^-3b7NgACeUnY#l)MfaMG0qAc7=e zBpIJl@F}$w!-8!tDPya5P9;eF^L^avk@)2J6Q5)3_#BN-KK^j>h65`N4a!V9hIxE) zbb534u0SyHc@5*u|MNVm8ip3s24e8ktky@1ivi>|Nxijc0Vdi;yn0 z1Jl54No5*pdlzX_F*Zz_fItLj)2L{Pg}=5v77NX`-bMSEHC~YKjq_T@m4$qqwlyv) zboAi-?Y)b1IZUKEB?mgFchMs4=U60Yk5F-viXW-CM8!=i?o;s$3x~>_*1ISVpEB{u z+*;gU zE{3#4A;gHZEA;@j$BGc8CebW<3uZj!2n*)|p?Sz8pSxyU(lVecfE--P{UkJXQH(lm2N-dq0^{3Yrp1nZID4X-O2!)86cLhYE+oj z0QwxWRii3oHfqh|P#B|gQ?)f)-Bem`FJg`$?t7&3*0|~H$uNH28Y89?wlfx?+B~WiV6n`c=%#u{=cDO}Gk&_sktS^lqbrMa(KTnH&6eg&j83O=)vbse zugyWaHIWUpJ&^7b5Cf2IOJt~aDALXI@6qT0K(jjYf_?tqw^1UX4!ma{i*3AvM;?Z}R?jPGg*0eHnF$ zQ^4fDPVBy5*4Ny?nz&WC?8yb$qXW#NyE2HK5r9G%wmHLgWpo{b)vQZsl+|{tZJ0H! z1@g5dwPUXZz@OLfv(8E}B?d&g#AY{4i4A6alfOj%X$O%r{C%@q?afV#oZWPZ&RVyI zY{T%OFDsfQ=UY#t`B+O)yd~}57A$+v%yrczfXq$KPV$OPOw+U4bCV*HW22cMONVIgZ`Mg@ zAC_ck6z#GkniOaNa<3-pereBmC+!^(l<


^#6-aFef{Ib`Q(pn!kN;(b}`$o!LyWR;l{LU@W*(sq4=cKekjnj5%RIUXz7V<#+1^Z2~Jv^qqodnQ+O-g`gF}e^{Iq0)04N*N&O0 zA&kc}#4Zw=`*1c^KSh}2!$sPQ8oL)}!&TEiadNgH$<@=%moeCOH}|;CAnDy%8 zW3y;E{Ytl{!{d`v$LYDKWZO7>RIr zd=k$wVOEPKM`v%MV!!m&xwT>9EtXzo9G8(AZb=y0UH8zJ3AgtDK+9f6<}|OyZXYHN zEF3?mXvpCF?{zw@cVk%3ep+K=*a{-emMq4i^%KfWTtLw7B|#}&g3Xq&3?uhrx~>Tu zsyhi+_)ZLLPsfAreG5O_Ozner(_ro5{&y;!d^K%<_*< zOrGiQ!WzPYY^%UycXJm*x)UD~WwG&jVTrIF&54s47uUub-Mn60Y+}OvUV6*WLfwL1 z3@8hGg<4Wl19Z=NGRDM$7Cx!5jLu+!Kza;jRe8=TQ%e^U@=Yv5fj0XZ6rL2@kYQIg zGh4$sCxgW$RkwVZN-Hp2b#t?293$Y(B_8 zDb<5ZQM-37g1-~)e%m7=*>35BjEVWkJqWQ;ncCNBF4-0C(Oi6T(w9gZk({;P3vxWPkO8MIN3Js`gDiM(SL%{Z-$fgh3O=PiEME z)v8aL##<6z_C%_8D|Fw&S0Sv4|Mm3vBtrFB_u!8XxSPQKGq<&(Igr*3gN6PDP23(LX9wj|0e zDk=HAaL}Jy?f%yg-Cw$Zpwz!~=2Rg+fD1N4Rvl-xVc<TD$TjqSFq->-bKyeG*4HX0 z)!d#wv1P(Xft&%25I)D=n}t6ExoBg|cfqzD+uZx7o2?hLZsx>k>0wR_g{UAdiQW2x zFd&F)AHRCI(-9~25iNV6*Rt3UTcXXDl8`!7$NDp@Hga8Th$SH zehcEvC`Q&LZ>%T0tHZx+^ta0Pbe zdby7cZ}`ootIAp9(Ed92c*b?G&dXLcOy_ImjFy>y?t#SWj;ech>ss?{TnWl z^BAO>8ZcDQFmU^FBAz`KuX3L1Jcx6OwWd!RGw#m9194VMQfiVdF(t{?9`>oCfW&0P z9zs6JSD3gG%VxMXpMgJMQx?i;;^L~3Z23w4C@Q7NP?r75%VSe1yQO)*TBnq z?&ES(lG`+=zZkfdek<$?<$A?5NErIl;)phFa+AVKEM>6v%8}t0ubUGRB0t!jLe|ln)Lrx^m+rb6UC4S+~%r zgL=!2lg(+r9oMxOIcC_vttM?8{N4AhaQ7DiLJRl(1GnnU$$zGSYr+>X2Gx!w+NX@p zwAD{ri-jj__9nCSz_5v(tqH=VFfJtd%C+bcYY>Be;~KQG^fS1aPZ~0|w9sRwuhs&$*ClFQ8WU!=q%q;zK|$IyMt57-5y6E79V)Acw^~w4 zwC2PPL27gIT8&!u`EFg4O~{=5NVpflSq$!G>#b=X4H8q*S)G4nthNoKga2m`2^Zs- zO4wLqDl@dlSzTq?&vR%?DL+&lNM zwPti}D;u;1JuQ>bwX1aCTH04Sx`60V>F5R`r_!YQTg}2vZ>LJ~83P5X)DbFOZl!~9 zxu%C(CVi;cX0L1uzGamjN323j6xWnpsuPN$xSl9UI10%jNRJHoS;!To0DGkcQz;f*WWANn#{eYcXfQB9>lPbT3wF_wXSDGkjav| z+Qr%3>8Ljw6{EX*)?|9;?pd?t&$Hp&LQiw@r3!6+;XCgX4@)?2(k3vv#Pgia1|I{@ zskAmmx2mnPS-V7~V^%iM{>SJZ{t~EFA>AG40IfUH-E^)nr)*o%(|JCpdv8T^E{B5; zdz?qS^_|HV{LF9)tveZ4#&8BxYTv59&dFS(Zt#jPHm7O(VIBo>!Aai;jbgZ{q}><1 zgKfA z`6H28%9={A1v1GhzXTJ5ZX+~K<#NDmN}D0fZp1Y)#QmuL(?7}8W$GEO?Vv%8OGhs8 zNfN3WaSdAzJp=34e~5~4W?Z=dWMNEc+b&0q9#R|NypH8wj8P{`6LtAVRNaU0H{Coeju5$xzk62BQ;HWgXWr<8pXkhkB`z+ac z#JQN1)a)icwy8{*uqBQ&hB+NqhudN&j*d;W-eU}DV-VL?qZvIn!0OdBA|c^ylZL5@ z%Y++oTnrj4cr@lBdmcIGZ|!nUQ_DDg$~ip@*8O;niM3f8GwMrlo4frSTysNw)Bfxb zo*Zjt{L(5i!jh7np5>k}jgp#FwsGy#&iTDE-xSRmSKCc?x|=c4aXr#vxq*Z^jk%xH ztVfiOP3RNPg=vhIgw?vwFEGNp@mzwNtx(^_Y%Rn~TsRib1?B^=)eNUNd30l@E?uJ{D-eg(LI5*L&yXaku^qMYuXXtj4 zckZl@vLzJhoqtM*PfIP*GwKYDu1K$S>Ss5m1l@62)!vvGUZ%6_)xoKDh@h2S-`!}# zIlDe5Sjr64tqSB^~}cRANOj)FW5vKs3ywGR9M z^;6ecM+nGfZncgKki53mQ2_D_uUbbL$Z0xuK4?g|wEaIrg70P;~!r~u^L z-cSL^1O1=^kTVBB0r=uWEyxUzlLmr6$fqF7K#my-{vhvxJPNYQFdzi^B}fLoSrS?V z9l0A%e*r~u@YQMHb5K|Tjr1G0E@t;5|NURspYI$}Y7Hm=r@ z3-ZPITE}>h3rcGp%R%~1u667MIT++GAh&^h3es&#t-}CcP1yu83FM-wwT|u}Ye3q^ zL#Fq%T1O?wG1F@u2S8SXtcHl)XF$s#0vpI`z`KIPUs4XWLj)ingDeB-HM7>S9%Ss? zTE`iXeHH*Q$TEzD?zC0}cItb4>g_iG(_Ai1?r5M-ARY8`7p?*6dW@fAq@N41VCAd^0Z2E!Y{o}bh@ z!a$B*U+c&Qxp+gZV)%IG)E0BSoL4@#4%cLE(j@BS^ zcGfyzfii=4)jAe|oB?th$n_x4fczTdeUQ!eKo@(%CI>PDzlVY# z*MM9O(sTw2g6snF3dqwxKtXto%bbO-1$pcolmqEj1zijB_aC7g$oQXN5`tuZfpQ?b zfqVt>?0F~$uXr`TLeGMn{Tr0?h4p_3GK&BRy$A(Cb^-Yd$kUggAV}tNts@Y=hxFtM z6a<-dwbn5h^3<=0pAlHCA4Du_G`bRM7V76z2 ztPT)f+PDa(O%GqeCM86qaSg0x|GsiaU*>~w7(ANzdrx^U0EZ1tO7IAf{6+4&NSKnw z1+zDiuo}zFobUyfc9n1m%cm;gC63jV?u zSbh*BT*C5vi0~52YYhbdrXcTz2~Dv4J3{D#WlW4P1Vo+9D z0(m$hjIwwh#)J9-&p89?^Mn~ka|C8W#+dh2S9Qp}K%WD3|F5d6s=KSZ>;L=SKY#11 zuMoZ7U)K=5F;GVh0sVV|P9Qqja%fvsG*?QsXBq^+37ls zXvcJ&Pjr5|-b(avx-KJnJ6&HPI%S5gA(}Z;M?DPs`7E74bV{a9dsxK;?9bFIiMnU& zxFpqHpL$pY227c)KP91_b98W`ih3`-%RXtuGSI&e1;+jbEr+z(7FuLNXK+a{}vpTRNW{-XipcfaK;us=2FKW4F@@ zP&Rh115cA&lrBtC%>q(#^;T3?!Qa;E|4LHr0%CLZ71DM&SJxz|?!(@Q#ouLo0QKpl z*8>%#W_}*lH(UokiRHZB3|^ipW=26~F1D8k0wMEQbKN0Xwb3gcQSPRxOKR)l2z|J@ ze)SR9o0+foKcb>yv#_fSB?f&PvR>tO73T@iq?V@ekJwCBt|a-kY1Ozcz(!)~xb9uY z0~vC2`}5-NZ`j7_b>DG!7-Y7t7I&}f_Q@)$Pd2c1FG{_y@2*F>sY_lesI7|u4g9#7 zeih9O!O@TNB6chT?iH{C;M$i3)C_um1-SYZG4cG}CTJ$dW8?M~*4B-O>>byKo1P|q z3i$i5A7=XSQ|tM;;QzE98G;XgD)C!89w?xb{yuU6kaNId zvExQSQ{Z<^^_#<0n?64RY+o!*xCmSK=-p5p@<(ly-aXNjf*~?wAi(C>rj54UtZh;{ zK-U%lH#F21Qs1B=^wTZK{LZIAF@{g=*+E|^z&>vjr?X;u@ao*O;79>00ak7kNvwX< zpx9;z!EcZrnCk8B?Ls1=t$aJJu2B;*@c9DLh%T^N-}o66u*d@NZ->oXwm(E-u0Of+nUK-eMHPy&H2$nE|>W0UCCgGXa* zu0mk>2Rdyu29GxG;txc?Edt$;LH=;q2(%bTfpkO!%5?%N1<~)tCmm%4bc>RM?9en~ zb7O7<<)j}SGcHU$2Z1k-)z*DXE|A0ZqcX*3^c|$1Imc`3#`uhWQvK-D4?i{dmq<^y z#(Me~G-VVjJyNFg$Ec_lsSsFPCIVGD4OmbS`0Y;`ehA$IO*knnIUdA)Q2~LsKIEoU zLf|CwRMT0jM8JdWHsm7~h)3*pN8)M%V^k1FdKLuco-&aUvJ3*xo|4W84dTu?2!XR7 zo6cxK_fy{>)ionpp@T7hf~vvaeTE0rjR}AGj9A#wh%F={(`xexTcG8(^Cu#Z#R82A zAdsmeN2&*=ZU#ROIr4JqrFcw;`rdBt)7#~!avC{wpN74?;Lfse6?(n`-!!#4kR8Dn z?wqjm>_|5(gVEO<4FyC2L6|!Z-B)DbegLr}MQ2P(uvH^}Y=nz0K_$XuKS&W}Pc~GREbctIPd_jIvTF%XXD+OHm&w@4?w@XY?2hD@v|h z^A+wjaGyZMUT6AU=lWge`&}2vHAaL>3KMJtRQfn`#8m%H-^v#D38;I_k* ztA+YcGgREfA^~W$Org~T1=GNkOQI0bW(p-)R9HJc6!9nYp(&L*Y$hIJ9#7y)tR|)$ z?9WuRJNSN#DVWfvShc^^)jdr>RX@h@Oy68%JWQ#Q>p6Y-8ZTQgd}~L<4!=4q)1@j4 z6@6K+G$KP?SBWOz5FVCptZ#y;bSQZ?UNhl1-KKL#W(c2fLaypwbJW>hj%|ThBBGo| zj_t<=Fz_H}j!v4Z+VpK)-y&ZDw_|(87jNPmPtc3zsu5#6;;%2ixf7b!5aG{??hYmL z8glVBA`u`uV4jNe+V=VKTRPQgzWqUbg|ET5r{4>2?WAVh3&-NH^j>&d8<6sydaNC)krl2USMIIl9#oIY48}(yP zsu5oQo9d?$LA`RQqbDMos-n?V5gE%obBS1?@2Fl-niGc)Ba z{7(+8@>4WK6urQToGv1dcefb>dj&UHHF&l|uFf!qMH8t}zCg94+#bpC|ZcKm2XN@le{?;m7#5R4DPo`(nu?0|))^0>O{_;hzY8 z$`6mkT1tA(0XMVJ#!Q+p%Ka*w5WK<<55k^7imv+M;{>nt!~Z0B)g7Ey14B4%_&LExdHop8u#r}>(f%+tnXbr_0Wg4=v2Rp&jaIz*l^YFazLF5wX~!$$wFp}7GW%{AO-}PIL8DZO-~n4%$+u9 zjCQTS(ewAho-RLKp&KD8osb8T{cG~W8T04^_$b1W1GVzb!KWBVL`m03e&sBdnui9l zs(7Oh&z?oTQXK3d_&Xw>zny_~SPrQi5&Tj=)?@Wo7~CmN4hZw!6qzGma-CUBoG9$9 zS_%3{{mx}F$OM-v#7X#a0syM;eOb{Z*haTp03+Ey) zJ>L&R zhB#_N?uy{k`m(&4pDCym-kLr7Repi^2Qe^0@Y-it^CZD13jSD2Rz%O|sJuxyjcvQb zBJu7`=Gbt#Y$d!uip222zRtI5!@lST8#oCi;{{(*#~SUh(~T|l=A?~`pA;YSL_TFX z<92jcFy7Kh5TER-b5b9A221lrsrRl7uU$a?Pw-EAvtM=*dk~K(cxfI=pWw-%*1i(Y z3f^71-44?x!8`thmT1HXAH^N{$(n-*9?(8Rm%8zHtpmH-b#`Rdb~^J zgxB;x<|l^faFfb&yXNz+G-B(VAkj$c<8 z+*QtiM1j+j@mObaQ})v?2@|Elg?(JX##g#Nv=D1nuCN=GG25=+Zwh|xfN!<^z{5;B zd0Hg?n#2Zez|{)=j;ukFq&S}T?76!;%hOo{mDz$vCNf~7;d#LaZDlz-lQtUMjC#8g zk$Flc$s`ta{zkaT6dIeX*%fVww|@urAxZ9KtgSS`Upm1GR*0T_!H-I$+BO~%{E2NW zXgl?!;ExXU?UUP#dz}mNOu`O-Uk^LtVc z6+SvBhMU&+DzoW8pGs%o_qq+~EAnMEESJI7oNOJoQiVsZ6LuR}!0gcNGi=wNS?Ygf z6|5;_C0As1M8XIqt}vanQgxWt{R(r-nK)xRva60v^*q6|1pibPHk$#j6g=`97PO_(TEWlXV!-Zc9Xqq%RbMl1yC)I2hy0#9K_q?} z!tV4DjY|Z-CbyP${u~kfXSqePiPTNOqaR{DRz40rZ!CF7;S=p0LnOzutM3xQ2mGFE z+AZp$;GI{qOSVU^3cf&YAQQx6cURVbD3JBoiPyv6X4Q#F6q(@?iZ&xzFZjNs(%4lh z(WM6UnOBSRHAup>|t{k26vch|8*QhpkUUnQ^TDC^5ZDHODY~J~spjFe-k;Q6l zpkDmCY8lvjz?~N%cPh^7)V1`6R=r&Mv(5NPlu_A1M{iLFRIh$HI{Gygp_6v0@Z$6F zJxW8is-bTDHa7E_r*q~%@#y@8BeI{)d?sbyJZDx~?*aPSV!SCi12#%myro_b@UhgY zcthN@(wukHf&g9duG$gMtdY(yQE__YJ{9UJ(kDt(&zAPY!_rHUx&|^~_Gre^LOp1Y z>KSZLbgKI4MSE2LmiFAkQg@&(+k@)%c%B1R2RIbJYn`g#L_B#;yu+f z%$|o>TBUCTZdv~jU#86L>pJ0m)w78_2EnPwqW9H^fKE+y+50N4r9B<7w7gE&01vZ| zr7aE7d3cwGPT8v>!t4o&rQ`JSy|8Q#NGvUBtIPI6Rs8|UQf0z!oxTn6FneHEzJlRU zv9J#o>=DUT;klVt1YWRxbXB=Rf3Q#W53|Q3l`C0KgucB`#fRF%kyTdvp#9Wo@?b4= zjfG9KiuS{(M|d9L#k0|J;-v^LrJi?tzZ%fQUXG_1W}K}aU9AA%d(M#dl|35S)0Ym@* delta 44213 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

p1^>)(KWeTAr-$H1qf zPv{L^4!#cAf&w&0g=d=04JBRLaDPUCX)lTets0G5Q^edY_HM;KO7gR>iiYoL$$K66 z{4MoEjwK%P_HFUGtcq!G>Oz%RYaJegfr9{Y6=0YC!97&Vw$1dT(-M1zk`*~QW>yf`>UoQt8^53EJ&F+4@GTesTMci7q? zArawPdSkqpI(4u05jwF|kBbrik_vfOh}L$0x&C9=+WUcM#pGgs058G#G!r~2UE+TA zLjhV)Lx`vG!*;(N8t-B@s@YTyeh~(l;js9T+quRjw>bsze;*O9mAqklLqFEDOx6>gG4_ZOFOOnBfxLQ5=G}Xi@^(FNA=$z?z43Azo4n)0+z+LPJtmAX`!ApwPU6x+SSQGd7Lq64iOl)b#$mc$iZlXY|1dwcA(I5+5RyDoIfwcAIdS?$|4 zC8GQLdNrX}Ep zYsViQ$k|7xu+6XA{ifXI@3YZRmCLWRZHp^O5^S*;KcN^=dwF6Nxv`gMe61w`#x5j_3h^UR%3Q z_ET)<_WyAX5Nqzz57^9z?*Hp`xXV948Kh@YRpZ>M12(&f?)uk^b4U4Jcl&F{xt1}C zRd@Mo$6NpGVV57XS&6#GKS3yc;V?$V4YrfaBzKeoUz~{h#7U%9w0tOi=;@$Mi{t?3 zFeaDg@( Date: Thu, 23 May 2024 01:39:37 -0300 Subject: [PATCH 07/14] min cuda and min cuda axis --- norch/csrc/cuda.h | 4 ++++ norch/csrc/tensor.cpp | 55 ++++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index b0ccbf2..766ce67 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -21,6 +21,10 @@ __global__ void max_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size); __host__ void max_tensor_cuda(Tensor* tensor, float* result_data, int axis); + __global__ void min_tensor_cuda_kernel(float* data, float* result_data); + __global__ void min_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size); + __host__ void min_tensor_cuda(Tensor* tensor, float* result_data, int axis); + __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.cpp b/norch/csrc/tensor.cpp index d94a3da..15a66bb 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -365,7 +365,6 @@ extern "C" { int ndim; int* shape; if (axis == -1) { - shape = (int*) malloc(sizeof(int)); shape[0] = 1; ndim = 1; @@ -379,26 +378,20 @@ extern "C" { ndim = tensor->ndim - 1; } - int size = 1; + int axis_size = 1; for (int i = 0; i < ndim; i++) { - size *= shape[i]; + axis_size *= shape[i]; } if (strcmp(tensor->device, "cuda") == 0) { float* result_data; - cudaMalloc((void**)&result_data, size * sizeof(float)); - //cudaMemset(result_data, INFINITY, size * sizeof(float)); - //min_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { - float* result_data = (float*)malloc(size * sizeof(float)); - if (result_data == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); + if (axis == -1) { + cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); + } else { + cudaMalloc((void**)&result_data, axis_size * sizeof(float)); } - min_tensor_cpu(tensor, result_data, size, shape, axis); + min_tensor_cuda(tensor, result_data, axis); if (keepdim) { if (axis == -1){ @@ -414,11 +407,39 @@ extern "C" { } shape[axis] = 1; ndim = tensor->ndim; - } + } + } - return create_tensor(result_data, shape, ndim, device); - } + + } + else { + float* result_data = (float*)malloc(axis_size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + min_tensor_cpu(tensor, result_data, axis_size, shape, axis); + + if (keepdim) { + if (axis == -1){ + ndim = tensor->ndim; + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = 1; + } + } else { + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = tensor->shape[i]; + } + shape[axis] = 1; + ndim = tensor->ndim; + } + + } + return create_tensor(result_data, shape, ndim, device); + } } Tensor* sub_tensor(Tensor* tensor1, Tensor* tensor2) { From 702ebaf87cc4137dbffbf6285855b37162d99c9e Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 02:09:32 -0300 Subject: [PATCH 08/14] 1D, 2D and 3D transpose cuda --- norch/csrc/cpu.cpp | 6 ++-- norch/csrc/cuda.cu | 70 +++++++++++++++++++++++++++++++++++----- norch/csrc/cuda.h | 10 ++++-- norch/csrc/tensor.cpp | 25 ++++++++++++-- tests/test_operations.py | 29 +++++++++++++++-- 5 files changed, 123 insertions(+), 17 deletions(-) diff --git a/norch/csrc/cpu.cpp b/norch/csrc/cpu.cpp index 4e27010..40eb3b5 100644 --- a/norch/csrc/cpu.cpp +++ b/norch/csrc/cpu.cpp @@ -375,14 +375,14 @@ void transpose_2D_tensor_cpu(Tensor* tensor, float* result_data) { } void transpose_3D_tensor_cpu(Tensor* tensor, float* result_data) { - int depth = tensor->shape[0]; + int batch = tensor->shape[0]; int rows = tensor->shape[1]; int cols = tensor->shape[2]; - for (int i = 0; i < depth; i++) { + for (int i = 0; i < batch; i++) { for (int j = 0; j < rows; j++) { for (int k = 0; k < cols; k++) { - result_data[k * rows * depth + j * depth + i] = tensor->data[i * rows * cols + j * cols + k]; + result_data[k * rows * batch + j * batch + i] = tensor->data[i * rows * cols + j * cols + k]; } } } diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 7c193fa..bda8a7d 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -1011,23 +1011,46 @@ __host__ void zeros_like_tensor_cuda(Tensor* tensor, float* result_data) { cudaDeviceSynchronize(); } -__global__ void transpose_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols) { - int tid_x = blockIdx.x * blockDim.x + threadIdx.x; - int tid_y = blockIdx.y * blockDim.y + threadIdx.y; - if (tid_x < cols && tid_y < rows) { - result_data[tid_x * rows + tid_y] = data[tid_y * cols + tid_x]; +__global__ void transpose_1D_tensor_cuda_kernel(float* data, float* result_data, int size) { + + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < size) { + result_data[i] = data[i]; } } -__host__ void transpose_tensor_cuda(Tensor* tensor, float* result_data) { +__host__ void transpose_1D_tensor_cuda(Tensor* tensor, float* result_data) { + + int number_of_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + transpose_1D_tensor_cuda_kernel<<>>(tensor->data, result_data, tensor->size); + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); +} + +__global__ void transpose_2D_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols) { + int i = blockIdx.x * blockDim.x + threadIdx.x; + int j = blockIdx.y * blockDim.y + threadIdx.y; + + if (i < rows && j < cols) { + result_data[j * rows + i] = data[i * cols + j]; + } +} + +__host__ void transpose_2D_tensor_cuda(Tensor* tensor, float* result_data) { int rows = tensor->shape[0]; int cols = tensor->shape[1]; dim3 threadsPerBlock(16, 16); - dim3 number_of_blocks((cols + threadsPerBlock.x - 1) / threadsPerBlock.x, (rows + threadsPerBlock.y - 1) / threadsPerBlock.y); - transpose_tensor_cuda_kernel<<>>(tensor->data, result_data, rows, cols); + dim3 number_of_blocks((rows + threadsPerBlock.x - 1) / threadsPerBlock.x, (cols + threadsPerBlock.y - 1) / threadsPerBlock.y); + transpose_2D_tensor_cuda_kernel<<>>(tensor->data, result_data, rows, cols); cudaError_t error = cudaGetLastError(); @@ -1039,6 +1062,37 @@ __host__ void transpose_tensor_cuda(Tensor* tensor, float* result_data) { cudaDeviceSynchronize(); } +__global__ void transpose_3D_tensor_cuda_kernel(float* data, float* result_data, int batch, int rows, int cols) { + int i = blockIdx.x * blockDim.x + threadIdx.x; + int j = blockIdx.y * blockDim.y + threadIdx.y; + int k = blockIdx.z * blockDim.z + threadIdx.z; + + if (i < batch && j < rows && k < cols) { + result_data[k * rows * batch + j * batch + i] = data[i * rows * cols + j * cols + k]; + } +} + +__host__ void transpose_3D_tensor_cuda(Tensor* tensor, float* result_data) { + + int batch = tensor->shape[0]; + int rows = tensor->shape[1]; + int cols = tensor->shape[2]; + + dim3 threadsPerBlock(8, 8, 8); + dim3 number_of_blocks((batch + threadsPerBlock.x - 1) / threadsPerBlock.x, (rows + threadsPerBlock.y - 1) / threadsPerBlock.y, (cols + threadsPerBlock.z - 1) / threadsPerBlock.z); + transpose_2D_tensor_cuda_kernel<<>>(tensor->data, result_data, rows, cols); + + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); +} + + __global__ void assign_tensor_cuda_kernel(float* data, float* result_data, int size) { int i = blockIdx.x * blockDim.x + threadIdx.x; diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index 766ce67..a684ee2 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -73,8 +73,14 @@ __global__ void zeros_like_tensor_cuda_kernel(float* data, float* result_data, int size); __host__ void zeros_like_tensor_cuda(Tensor* tensor, float* result_data); - __global__ void transpose_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols); - __host__ void transpose_tensor_cuda(Tensor* tensor, float* result_data); + __global__ void transpose_1D_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols); + __host__ void transpose_1D_tensor_cuda(Tensor* tensor, float* result_data); + + __global__ void transpose_2D_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols); + __host__ void transpose_2D_tensor_cuda(Tensor* tensor, float* result_data); + + __global__ void transpose_3D_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols); + __host__ void transpose_3D_tensor_cuda(Tensor* tensor, float* result_data); __global__ void assign_tensor_cuda_kernel(float* data, float* result_data, int size); __host__ void assign_tensor_cuda(Tensor* tensor, float* result_data); diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 15a66bb..22739b6 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -1422,7 +1422,20 @@ extern "C" { float* result_data; cudaMalloc((void **)&result_data, size * sizeof(float)); - transpose_tensor_cuda(tensor, result_data); + switch (ndim) { + case 1: + transpose_1D_tensor_cuda(tensor, result_data); + break; + case 2: + transpose_2D_tensor_cuda(tensor, result_data); + break; + case 3: + transpose_3D_tensor_cuda(tensor, result_data); + break; + default: + fprintf(stderr, "Transpose only supports tensors up to 3 dimensions.\n"); + exit(-1); + } return create_tensor(result_data, shape, ndim, device); } else { @@ -1479,7 +1492,15 @@ extern "C" { float* result_data; cudaMalloc((void **)&result_data, size * sizeof(float)); assign_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + + Tensor* new_tensor = create_tensor(result_data, shape, ndim, device); + for (int i = 0; i < ndim; i++) { + new_tensor->strides[i] = tensor->strides[i]; + } + new_tensor->strides[axis1] = tensor->strides[axis2]; + new_tensor->strides[axis2] = tensor->strides[axis1]; + make_contiguous(new_tensor); + return new_tensor; } else { float* result_data = (float*)malloc(size * sizeof(float)); diff --git a/tests/test_operations.py b/tests/test_operations.py index d443260..262cee4 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -471,8 +471,33 @@ class TestTensorOperations(unittest.TestCase): self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + def test_1D_T(self): + """ + Test transposition of a 1D tensor. + """ + norch_tensor = norch.Tensor([1, 2, 3, 4]).to(self.device) + norch_result = norch_tensor.T + torch_result = utils.to_torch(norch_result).to(self.device) - def test_transpose_T(self): + torch_tensor = torch.tensor([1, 2, 3, 4]).to(self.device) + torch_expected = torch_tensor.T + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + + def test_2D_T(self): + """ + Test transposition of a 2D tensor. + """ + norch_tensor = norch.Tensor([[1, 2, 3], [4, 5, 6]]).to(self.device) + norch_result = norch_tensor.T + torch_result = utils.to_torch(norch_result).to(self.device) + + torch_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]]).to(self.device) + torch_expected = torch_tensor.T + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + + def test_3D_T(self): """ Test transposition of a tensor: tensor.T """ @@ -481,7 +506,7 @@ class TestTensorOperations(unittest.TestCase): torch_result = utils.to_torch(norch_result).to(self.device) torch_tensor = torch.tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) - torch_expected = torch.transpose(torch_tensor, 0, 2) + torch_expected = torch_tensor.T self.assertTrue(utils.compare_torch(torch_result, torch_expected)) From d2fc1e36177033eeb62aa3208794896213045ec6 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 02:27:30 -0300 Subject: [PATCH 09/14] make contiguous cuda --- build/cpu.o | Bin 15536 -> 16000 bytes build/cuda.cu.o | Bin 203032 -> 220464 bytes build/tensor.o | Bin 52872 -> 54176 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/build/cpu.o b/build/cpu.o index 2ee4a6fbffdf99db5f658e321d6bd26a92b6e34c..ecb6dd6dc0542056100f301bf9cd9330f9d2305b 100644 GIT binary patch delta 997 zcmdl`*-$${gQ>xCqt;y6dXMHe1|FTYFFZO+A9!?z-Z<|1fdL3Sx?Nv%JLp)te&Fxj z3FIGl{Q?s1cKy)l`s29k9}owkM#IwePi;cC>mQF99=#&1P>CBJj2F5Mx?O+F{Qj@= zAV{T0w*yCa=pT>dOCARwF@dBR_}3q_XLS97RWAov@6XQAAI+|R7++6;7{SmT`UP&n zA)sp}ACQ)||G@at{Qv*|P$eFn$6vsl2eK5E9}4uP07PZz4Uf(MjtM6>?~@H=+AN^p z!=fq!)VP5eq?>_3kr7C^@(HvtIrFkHOEB`Vb1*0Xg)U4^R8eO9GPzYno=Jpd^D-4J zR#mWCpj;&j1A`C)Ged_QkOKsT5QepejT*2Wt7V2pXB?CT6F`C+FvtWTuzqmljXv*A-<7$ecV^FPjal^W0=beeul- z`W!6vQBd1}MleVM@gHDtfj|}x@rOv_=1A%j<-sO1FaarcAhv;U88V^bAoDGO7-oJg zL_7_yK?kZ~E}B6w@nbj)x`ji1h62Pukj2)U?;3w*a=HSIKad+i7#0^l(8OUeAOX?~ z1Tgjd3Y&kKO=IM3Pyh=nN01*&ioqWl{jOm5~FjmDTD_Cm4mSNH<>wpvkK@AS^ zr4Vs526TgV;?UqO4>1s=-fHq%Q}NAfOz$vh-C%|YgWL(iu+aE{CjL%t^C^pIjJ)ws zW5Bv5AG8sk++Zca#i0)|6edRjsRV_|vw&2O0z|)!2GazE$x^mHq)$ diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 23217f653b003eaca8b8aa1e56ca8c57bafc7ee6..128ca1f4ae3b5dd03e060dcb9a8ae403c6516737 100644 GIT binary patch delta 44746 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 delta 33055 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 literal 52872 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 From 38e629fc386757f780a08760f89ed6af141a56cd Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 02:27:46 -0300 Subject: [PATCH 10/14] make contiguous cuda --- norch/csrc/cpu.cpp | 19 +++++++++++++++++++ norch/csrc/cpu.h | 1 + norch/csrc/cuda.cu | 42 ++++++++++++++++++++++++++++++++++++++++++ norch/csrc/cuda.h | 3 +++ norch/csrc/tensor.cpp | 37 +++++++++++++------------------------ norch/libtensor.so | Bin 250496 -> 268008 bytes 6 files changed, 78 insertions(+), 24 deletions(-) diff --git a/norch/csrc/cpu.cpp b/norch/csrc/cpu.cpp index 40eb3b5..63e1615 100644 --- a/norch/csrc/cpu.cpp +++ b/norch/csrc/cpu.cpp @@ -395,6 +395,25 @@ void assign_tensor_cpu(Tensor* tensor, float* result_data) { } } +void make_contiguous_tensor_cpu(Tensor* tensor, float* result_data, int* new_strides) { + + for (int i = 0; i < tensor->size; i++) { + int index = 0; + int offset = i; + for (int j = 0; j < tensor->ndim; j++) { + index += (offset / new_strides[j]) * tensor->strides[j]; + offset %= new_strides[j]; + } + result_data[i] = tensor->data[index]; + } + + // Free old data and update tensor properties + free(tensor->data); + free(tensor->strides); + tensor->data = result_data; + tensor->strides = new_strides; +} + void sin_tensor_cpu(Tensor* tensor, float* result_data) { for (int i = 0; i < tensor->size; i++) { result_data[i] = sinf(tensor->data[i]); diff --git a/norch/csrc/cpu.h b/norch/csrc/cpu.h index 1d9547b..9a27a26 100644 --- a/norch/csrc/cpu.h +++ b/norch/csrc/cpu.h @@ -30,6 +30,7 @@ void transpose_2D_tensor_cpu(Tensor* tensor, float* result_data); void transpose_3D_tensor_cpu(Tensor* tensor, float* result_data); void transpose_axes_cpu(Tensor* tensor, float* result_data, int axis1, int axis2, int* new_shape); void assign_tensor_cpu(Tensor* tensor, float* result_data); +void make_contiguous_tensor_cpu(Tensor* tensor, float* result_data, int* new_strides); void sin_tensor_cpu(Tensor* tensor, float* result_data); void cos_tensor_cpu(Tensor* tensor, float* result_data); void sigmoid_tensor_cpu(Tensor* tensor, float* result_data); diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index bda8a7d..064c3d1 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -1115,6 +1115,48 @@ __host__ void assign_tensor_cuda(Tensor* tensor, float* result_data) { cudaDeviceSynchronize(); } +__global__ void make_contiguous_tensor_cuda_kernel(float* data, float* result_data, int ndim, int size, int* strides, int* new_strides) { + + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < size) { + int index = 0; + int offset = i; + for (int j = 0; j < ndim; j++) { + index += (offset / new_strides[j]) * strides[j]; + offset %= new_strides[j]; + } + result_data[i] = data[index]; + } +} + +__host__ void make_contiguous_tensor_cuda(Tensor* tensor, float* result_data, int* new_strides) { + + int* d_strides; + cudaMalloc((void **)&d_strides, tensor->ndim * sizeof(int)); + cudaMemcpy(d_strides, tensor->strides, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + + int* d_new_strides; + cudaMalloc((void **)&d_new_strides, tensor->ndim * sizeof(int)); + cudaMemcpy(d_new_strides, new_strides, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice); + + int number_of_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + make_contiguous_tensor_cuda_kernel<<>>(tensor->data, result_data, tensor->ndim, tensor->size, d_strides, d_new_strides); + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); + + // Free old data and update tensor properties + cudaFree(tensor->data); + free(tensor->strides); + tensor->data = result_data; + tensor->strides = new_strides; +} + __global__ void sin_tensor_cuda_kernel(float* data, float* result_data, int size) { int i = blockIdx.x * blockDim.x + threadIdx.x; diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index a684ee2..cc7b385 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -85,6 +85,9 @@ __global__ void assign_tensor_cuda_kernel(float* data, float* result_data, int size); __host__ void assign_tensor_cuda(Tensor* tensor, float* result_data); + __global__ void make_contiguous_tensor_cuda_kernel(float* data, float* result_data, int ndim, int size, int* strides, int* new_strides); + __host__ void make_contiguous_tensor_cuda(Tensor* tensor, float* result_data, int* new_strides); + __global__ void sin_tensor_cuda_kernel(float* data, float* result_data, int size); __host__ void sin_tensor_cuda(Tensor* tensor, float* result_data); diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 22739b6..d5bfa71 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -1522,17 +1522,10 @@ extern "C" { } void make_contiguous(Tensor* tensor) { - float* new_data = (float*)malloc(tensor->size * sizeof(float)); - if (new_data == NULL) { - // Handle memory allocation failure - return; - } - + int* new_strides = (int*)malloc(tensor->ndim * sizeof(int)); if (new_strides == NULL) { - free(new_data); - // Handle memory allocation failure - return; + fprintf(stderr, "Memory allocation failed\n"); } // Calculate new strides assuming C-contiguous order @@ -1542,21 +1535,17 @@ extern "C" { stride *= tensor->shape[i]; } - // Rearrange data - for (int i = 0; i < tensor->size; i++) { - int index = 0; - int offset = i; - for (int j = 0; j < tensor->ndim; j++) { - index += (offset / new_strides[j]) * tensor->strides[j]; - offset %= new_strides[j]; - } - new_data[i] = tensor->data[index]; - } + if (strcmp(tensor->device, "cuda") == 0) { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + make_contiguous_tensor_cuda(tensor, result_data, new_strides); - // Free old data and update tensor properties - free(tensor->data); - free(tensor->strides); - tensor->data = new_data; - tensor->strides = new_strides; + } else { + float* result_data = (float*)malloc(tensor->size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + } + make_contiguous_tensor_cpu(tensor, result_data, new_strides); } } +} diff --git a/norch/libtensor.so b/norch/libtensor.so index 0f5fce8d116a2aedf968b0000f094fb310b2e5c9..5f2b381cf0280b809ba912a7c6a7043e30972e43 100755 GIT binary patch delta 65257 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 KzmrJ)+gB3R{>8cG1c=b=hU^ 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 delta 53055 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 From a0bfd6a0eb0fc8dc8725561962068337fd739f1b Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 02:34:38 -0300 Subject: [PATCH 11/14] small fix 3D transpose --- norch/csrc/cuda.cu | 2 +- norch/csrc/cuda.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 064c3d1..87ba247 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -1080,7 +1080,7 @@ __host__ void transpose_3D_tensor_cuda(Tensor* tensor, float* result_data) { dim3 threadsPerBlock(8, 8, 8); dim3 number_of_blocks((batch + threadsPerBlock.x - 1) / threadsPerBlock.x, (rows + threadsPerBlock.y - 1) / threadsPerBlock.y, (cols + threadsPerBlock.z - 1) / threadsPerBlock.z); - transpose_2D_tensor_cuda_kernel<<>>(tensor->data, result_data, rows, cols); + transpose_3D_tensor_cuda_kernel<<>>(tensor->data, result_data, batch, rows, cols); cudaError_t error = cudaGetLastError(); diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index cc7b385..daeef28 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -79,7 +79,7 @@ __global__ void transpose_2D_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols); __host__ void transpose_2D_tensor_cuda(Tensor* tensor, float* result_data); - __global__ void transpose_3D_tensor_cuda_kernel(float* data, float* result_data, int rows, int cols); + __global__ void transpose_3D_tensor_cuda_kernel(float* data, float* result_data, int batch, int rows, int cols); __host__ void transpose_3D_tensor_cuda(Tensor* tensor, float* result_data); __global__ void assign_tensor_cuda_kernel(float* data, float* result_data, int size); From fb4f90b0cfb159ceb2936192f41af1317eb5040d Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 02:35:00 -0300 Subject: [PATCH 12/14] small fix 3D transpose --- build/cuda.cu.o | Bin 220464 -> 220464 bytes norch/libtensor.so | Bin 268008 -> 268008 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 128ca1f4ae3b5dd03e060dcb9a8ae403c6516737..4d96c07496451f5c75fa27a0e7cd608a52af7901 100644 GIT binary patch delta 9761 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 delta 9752 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 diff --git a/norch/libtensor.so b/norch/libtensor.so index 5f2b381cf0280b809ba912a7c6a7043e30972e43..7ce529929c5bd60a26f58686e7f25a42d4a6d924 100755 GIT binary patch delta 16745 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 delta 16803 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 MdO5LWT-Lh$AIW74wg3PC From d70e398773035c1649a4ab55c7c2fc8836073eb7 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 02:57:57 -0300 Subject: [PATCH 13/14] fix autograd cuda unittests --- tests/test_autograd.py | 272 +++++++++++++++++++++++++++++++---------- 1 file changed, 206 insertions(+), 66 deletions(-) diff --git a/tests/test_autograd.py b/tests/test_autograd.py index 2265c6d..82e6b61 100644 --- a/tests/test_autograd.py +++ b/tests/test_autograd.py @@ -24,8 +24,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + torch_tensor2 = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) + torch_result = (torch_tensor1 + torch_tensor2).sum() torch_result.backward() torch_tensor1_grad = torch_tensor1.grad @@ -46,8 +50,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + torch_tensor2 = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result = (torch_tensor1 + torch_tensor2).sum(axis=0).sum(axis=0).sum() torch_result.backward() @@ -65,8 +72,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + torch_tensor2 = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result = (torch_tensor1 + torch_tensor2).sum(axis=1).sum() torch_result.backward() @@ -87,7 +97,9 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) torch_result = torch_tensor.max() torch_result.backward() @@ -106,7 +118,9 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) torch_max_axis, _ = torch_tensor.max(axis=1) torch_result = torch_max_axis.sum() @@ -122,7 +136,9 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 1], [-4, 0]], [[5., 50], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 1], [-4, 0]], [[5., 50], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) torch_max_axis, _ = torch_tensor.max(axis=2) torch_result = torch_max_axis.sum() @@ -186,7 +202,9 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) torch_result = torch_tensor.min() torch_result.backward() @@ -205,7 +223,9 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) torch_min, _ = torch_tensor.min(axis=1) torch_result = torch_min.sum() @@ -221,7 +241,9 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 1], [-4, 0]], [[5., 50], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 1], [-4, 0]], [[5., 50], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) torch_min, _ = torch_tensor.min(axis=2) torch_result = torch_min.sum() @@ -242,8 +264,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True).to(self.device) # Shape (1, 2, 3) - torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True).to(self.device) # Shape (3) + torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True) # Shape (1, 2, 3) + torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True) # Shape (3) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) + torch_result = (torch_tensor1 + torch_tensor2).sum() torch_result.backward() torch_tensor1_grad = torch_tensor1.grad @@ -261,8 +287,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True).to(self.device) # Shape (1, 2, 3) - torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True).to(self.device) # Shape (3) + torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True) # Shape (1, 2, 3) + torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True) # Shape (3) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result = (torch_tensor2 + torch_tensor1).sum() torch_result.backward() @@ -283,8 +312,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad_sub = utils.to_torch(norch_tensor1_sub.grad).to(self.device) norch_tensor2_grad_sub = utils.to_torch(norch_tensor2_sub.grad).to(self.device) - torch_tensor1_sub = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) - torch_tensor2_sub = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True).to(self.device) + torch_tensor1_sub = torch.tensor([[[1, 2.5], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + torch_tensor2_sub = torch.tensor([[[1, 1.], [1, 1.9]], [[1, 1], [1, 1]]], requires_grad=True) + + torch_tensor1_sub.to(self.device) + torch_tensor2_sub.to(self.device) + torch_result_sub = (torch_tensor1_sub - torch_tensor2_sub).sum() torch_result_sub.backward() torch_tensor1_grad_sub = torch_tensor1_sub.grad @@ -304,8 +337,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True).to(self.device) # Shape (1, 2, 3) - torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True).to(self.device) # Shape (3) + torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True) # Shape (1, 2, 3) + torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True) # Shape (3) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) + torch_result = (torch_tensor1 - torch_tensor2).sum() torch_result.backward() torch_tensor1_grad = torch_tensor1.grad @@ -323,8 +360,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor2_grad = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True).to(self.device) # Shape (1, 2, 3) - torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True).to(self.device) # Shape (3) + torch_tensor1 = torch.tensor([[[1., 2, 3], [4, 5, 6]]], requires_grad=True) # Shape (1, 2, 3) + torch_tensor2 = torch.tensor([1.5, -1, 0], requires_grad=True) # Shape (3) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result = (torch_tensor2 - torch_tensor1).sum() torch_result.backward() @@ -346,8 +386,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad_div = utils.to_torch(norch_tensor1_div.grad).to(self.device) norch_tensor2_grad_div = utils.to_torch(norch_tensor2_div.grad).to(self.device) - torch_tensor1_div = torch.tensor([[[2, 5.1], [6, -8]], [[10, 12], [14, 16]]], requires_grad=True).to(self.device) - torch_tensor2_div = torch.tensor([[[1, 1], [2, 2.2]], [[3, 3], [4, 4]]], requires_grad=True).to(self.device) + torch_tensor1_div = torch.tensor([[[2, 5.1], [6, -8]], [[10, 12], [14, 16]]], requires_grad=True) + torch_tensor2_div = torch.tensor([[[1, 1], [2, 2.2]], [[3, 3], [4, 4]]], requires_grad=True) + + torch_tensor1_div.to(self.device) + torch_tensor2_div.to(self.device) + torch_result_div = (torch_tensor1_div / torch_tensor2_div).sum() torch_result_div.backward() torch_tensor1_grad_div = torch_tensor1_div.grad @@ -367,7 +411,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_div_scalar.backward() norch_tensor_grad_div_scalar = utils.to_torch(norch_tensor_div_scalar.grad).to(self.device) - torch_tensor_div_scalar = torch.tensor([[[2, 4.7], [6, 8]], [[10, 12], [14, 16]]], requires_grad=True).to(self.device) + torch_tensor_div_scalar = torch.tensor([[[2, 4.7], [6, 8]], [[10, 12], [14, 16]]], requires_grad=True) + + torch_tensor_div_scalar.to(self.device) + torch_result_div_scalar = (torch_tensor_div_scalar / scalar).sum() torch_result_div_scalar.backward() torch_tensor_grad_div_scalar = torch_tensor_div_scalar.grad @@ -385,7 +432,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_scalar_div.backward() norch_tensor_grad_scalar_div = utils.to_torch(norch_tensor_scalar_div.grad).to(self.device) - torch_tensor_scalar_div = torch.tensor([[[1, 2.23], [3, 4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor_scalar_div = torch.tensor([[[1, 2.23], [3, 4]], [[5, 6], [7, 8]]], requires_grad=True) + + torch_tensor_scalar_div.to(self.device) + torch_result_scalar_div = (scalar / torch_tensor_scalar_div).sum() torch_result_scalar_div.backward() torch_tensor_grad_scalar_div = torch_tensor_scalar_div.grad @@ -403,7 +453,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_power_st.backward() norch_tensor_grad_power_st = utils.to_torch(norch_tensor_power_st.grad).to(self.device) - torch_tensor_power_st = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + torch_tensor_power_st = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True) + + torch_tensor_power_st.to(self.device) + torch_result_power_st = (scalar ** torch_tensor_power_st).sum() torch_result_power_st.backward() torch_tensor_grad_power_st = torch_tensor_power_st.grad @@ -420,7 +473,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_power_ts.backward() norch_tensor_grad_power_ts = utils.to_torch(norch_tensor_power_ts.grad).to(self.device) - torch_tensor_power_ts = torch.tensor([[[2, 3], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + torch_tensor_power_ts = torch.tensor([[[2, 3], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True) + + torch_tensor_power_ts.to(self.device) + torch_result_power_ts = (torch_tensor_power_ts ** scalar).sum() torch_result_power_ts.backward() torch_tensor_grad_power_ts = torch_tensor_power_ts.grad @@ -438,8 +494,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor1_grad_matmul = utils.to_torch(norch_tensor1_matmul.grad).to(self.device) norch_tensor2_grad_matmul = utils.to_torch(norch_tensor2_matmul.grad).to(self.device) - torch_tensor1_matmul = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) - torch_tensor2_matmul = torch.tensor([[[1.1, 3], [4, 5]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + torch_tensor1_matmul = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + torch_tensor2_matmul = torch.tensor([[[1.1, 3], [4, 5]], [[6, 7], [8, 9]]], requires_grad=True) + + torch_tensor1_matmul.to(self.device) + torch_tensor2_matmul.to(self.device) + torch_result_matmul = (torch_tensor1_matmul @ torch_tensor2_matmul).sum() torch_result_matmul.backward() torch_tensor1_grad_matmul = torch_tensor1_matmul.grad @@ -466,8 +526,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor2_grad_matmul = utils.to_torch(norch_tensor2_matmul.grad).to(self.device) # Repeat the same process with torch tensors - torch_tensor1_matmul = torch.tensor([[[1., 2], [3, -4], [5, 6], [7, 8]] for _ in range(B)], requires_grad=True).to(self.device) - torch_tensor2_matmul = torch.tensor([[[2., 3, 1, 0, 4], [5, -1, 2, 3, 0]] for _ in range(B)], requires_grad=True).to(self.device) + torch_tensor1_matmul = torch.tensor([[[1., 2], [3, -4], [5, 6], [7, 8]] for _ in range(B)], requires_grad=True) + torch_tensor2_matmul = torch.tensor([[[2., 3, 1, 0, 4], [5, -1, 2, 3, 0]] for _ in range(B)], requires_grad=True) + + torch_tensor1_matmul.to(self.device) + torch_tensor2_matmul.to(self.device) + torch_result_matmul = torch.matmul(torch_tensor1_matmul, torch_tensor2_matmul) torch_result_matmul_sum = torch_result_matmul.sum() torch_result_matmul_sum.backward() @@ -498,8 +562,12 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor2_grad_matmul = utils.to_torch(norch_tensor2_matmul.grad).to(self.device) # Repeat the same process with torch tensors - torch_tensor1_matmul = torch.tensor([[1., 2], [3, -4], [5, 6], [7, 8]], requires_grad=True).to(self.device) - torch_tensor2_matmul = torch.tensor([[[2., 3, 1, 0, 4], [5, -1, 2, 3, 0]] for _ in range(B)], requires_grad=True).to(self.device) + torch_tensor1_matmul = torch.tensor([[1., 2], [3, -4], [5, 6], [7, 8]], requires_grad=True) + torch_tensor2_matmul = torch.tensor([[[2., 3, 1, 0, 4], [5, -1, 2, 3, 0]] for _ in range(B)], requires_grad=True) + + torch_tensor1_matmul.to(self.device) + torch_tensor2_matmul.to(self.device) + torch_result_matmul = torch.matmul(torch_tensor1_matmul, torch_tensor2_matmul) torch_result_matmul_sum = torch_result_matmul.sum() torch_result_matmul_sum.backward() @@ -523,7 +591,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_elemwise_mul_scalar.backward() norch_tensor_grad_elemwise_mul_scalar = utils.to_torch(norch_tensor_elemwise_mul_scalar.grad).to(self.device) - torch_tensor_elemwise_mul_scalar = torch.tensor([[[1.1, 2], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor_elemwise_mul_scalar = torch.tensor([[[1.1, 2], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + + torch_tensor_elemwise_mul_scalar.to(self.device) + torch_result_elemwise_mul_scalar = (scalar * torch_tensor_elemwise_mul_scalar).sum() torch_result_elemwise_mul_scalar.backward() torch_tensor_grad_elemwise_mul_scalar = torch_tensor_elemwise_mul_scalar.grad @@ -544,6 +615,10 @@ class TestTensorAutograd(unittest.TestCase): torch_tensor1_elemwise_mul = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) torch_tensor2_elemwise_mul = torch.tensor([[[1.1, 3], [4, 5]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + + torch_tensor1_elemwise_mul.to(self.device) + torch_tensor2_elemwise_mul.to(self.device) + torch_result_elemwise_mul = (torch_tensor1_elemwise_mul * torch_tensor2_elemwise_mul).sum() torch_result_elemwise_mul.backward() torch_tensor1_grad_elemwise_mul = torch_tensor1_elemwise_mul.grad @@ -561,7 +636,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_sin_tensor.backward() torch_result_sin_tensor_grad = utils.to_torch(norch_sin_tensor.grad).to(self.device) - torch_sin_tensor = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + torch_sin_tensor = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True) + + torch_sin_tensor.to(self.device) + torch_expected_sin_tensor = (torch.sin(torch_sin_tensor)).sum() torch_expected_sin_tensor.backward() torch_expected_sin_tensor_grad = torch_sin_tensor.grad @@ -577,7 +655,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_cos_tensor.backward() torch_result_cos_tensor_grad = utils.to_torch(norch_cos_tensor.grad).to(self.device) - torch_cos_tensor = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + torch_cos_tensor = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True) + + torch_cos_tensor.to(self.device) + torch_expected_cos_tensor = (torch.sin(torch_cos_tensor)).sum() torch_expected_cos_tensor.backward() torch_expected_cos_tensor_grad = torch_cos_tensor.grad @@ -595,7 +676,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result.backward() norch_tensor_grad = utils.to_torch(norch_tensor.grad).to(self.device) - torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor = torch.tensor([[[10, 10], [-4, -4]], [[5., 6], [7, 8]]], requires_grad=True) + + torch_tensor.to(self.device) + torch_sigmoid = torch.sigmoid(torch_tensor) torch_result = torch_sigmoid.sum() @@ -617,8 +701,12 @@ class TestTensorAutograd(unittest.TestCase): loss_norch.backward() # Backpropagate the loss grad_norch = predictions_norch.grad - predictions_torch = torch.tensor([1.1, 2, 3, 4], requires_grad=True).to(self.device) - labels_torch = torch.tensor([4, 3, 2.1, 1]).to(self.device) + predictions_torch = torch.tensor([1.1, 2, 3, 4], requires_grad=True) + labels_torch = torch.tensor([4, 3, 2.1, 1]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) loss_torch_expected.backward() # Backpropagate the loss grad_torch_expected = predictions_torch.grad @@ -643,8 +731,12 @@ class TestTensorAutograd(unittest.TestCase): loss_norch.backward() # Backpropagate the loss grad_norch = predictions_norch.grad - predictions_torch = torch.tensor([2.0, 1.0, 0.1], requires_grad=True).to(self.device) - labels_torch = torch.tensor(0).to(self.device) + predictions_torch = torch.tensor([2.0, 1.0, 0.1], requires_grad=True) + labels_torch = torch.tensor(0) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) loss_torch_expected.backward() # Backpropagate the loss grad_torch_expected = predictions_torch.grad @@ -661,8 +753,12 @@ class TestTensorAutograd(unittest.TestCase): loss_norch.backward() # Backpropagate the loss grad_norch = predictions_norch.grad - predictions_torch = torch.tensor([[0.5, 1.5, 2.5], [1.0, 2.0, 3.0]], requires_grad=True).to(self.device) - labels_torch = torch.tensor([2, 1]).to(self.device) + predictions_torch = torch.tensor([[0.5, 1.5, 2.5], [1.0, 2.0, 3.0]], requires_grad=True) + labels_torch = torch.tensor([2, 1]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) loss_torch_expected.backward() # Backpropagate the loss grad_torch_expected = predictions_torch.grad @@ -679,8 +775,12 @@ class TestTensorAutograd(unittest.TestCase): loss_norch.backward() # Backpropagate the loss grad_norch = predictions_norch.grad - predictions_torch = torch.tensor([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], requires_grad=True).to(self.device) - labels_torch = torch.tensor([1, 2]).to(self.device) + predictions_torch = torch.tensor([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], requires_grad=True) + labels_torch = torch.tensor([1, 2]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) loss_torch_expected.backward() # Backpropagate the loss grad_torch_expected = predictions_torch.grad @@ -697,8 +797,12 @@ class TestTensorAutograd(unittest.TestCase): loss_norch.backward() # Backpropagate the loss grad_norch = predictions_norch.grad - predictions_torch = torch.tensor([[0.5, 0.2, 0.1], [0.1, 0.5, 0.7]], requires_grad=True).to(self.device) - labels_torch = torch.tensor([[1., 0, 0], [0, 1, 0]]).to(self.device) + predictions_torch = torch.tensor([[0.5, 0.2, 0.1], [0.1, 0.5, 0.7]], requires_grad=True) + labels_torch = torch.tensor([[1., 0, 0], [0, 1, 0]]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) loss_torch_expected.backward() # Backpropagate the loss grad_torch_expected = predictions_torch.grad @@ -757,7 +861,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_reshape.backward() norch_tensor_grad_reshape = utils.to_torch(norch_tensor_reshape.grad).to(self.device) - torch_tensor_reshape = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor_reshape = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + + torch_tensor_reshape.to(self.device) + torch_result_reshape = torch_tensor_reshape.reshape(new_shape).sum() torch_result_reshape.backward() torch_tensor_grad_reshape = torch_tensor_reshape.grad @@ -775,7 +882,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_transpose.backward() norch_tensor_grad_transpose = utils.to_torch(norch_tensor_transpose.grad).to(self.device) - torch_tensor_transpose = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor_transpose = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + + torch_tensor_transpose.to(self.device) + torch_result_transpose = torch_tensor_transpose.transpose(axis1, axis2).sum() torch_result_transpose.backward() torch_tensor_grad_transpose = torch_tensor_transpose.grad @@ -792,7 +902,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_T.backward() norch_tensor_grad_T = utils.to_torch(norch_tensor_T.grad).to(self.device) - torch_tensor_T = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True).to(self.device) + torch_tensor_T = torch.tensor([[[1, 2.1], [3, -4]], [[5, 6], [7, 8]]], requires_grad=True) + + torch_tensor_T.to(self.device) + torch_result_T = torch_tensor_T.mT.sum() torch_result_T.backward() torch_tensor_grad_T = torch_tensor_T.grad @@ -813,8 +926,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor_grad_reshape_matmul1 = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor_grad_reshape_matmul2 = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[1, 2.1], [3, -4], [5, 6], [7, 8]], dtype=torch.float32, requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[1, 5.1], [0.1, -4], [0, 6], [7, 8]], dtype=torch.float32, requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[1, 2.1], [3, -4], [5, 6], [7, 8]], dtype=torch.float32, requires_grad=True) + torch_tensor2 = torch.tensor([[1, 5.1], [0.1, -4], [0, 6], [7, 8]], dtype=torch.float32, requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result_reshape_matmul = (torch_tensor1.reshape(new_shape) @ torch_tensor2).sum() torch_result_reshape_matmul.backward() @@ -835,7 +951,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_unsqueeze_0.backward() norch_tensor_grad_unsqueeze_0 = utils.to_torch(norch_tensor_unsqueeze.grad).to(self.device) - torch_tensor_unsqueeze = torch.tensor([[1., 2], [3, 4]], requires_grad=True).to(self.device) + torch_tensor_unsqueeze = torch.tensor([[1., 2], [3, 4]], requires_grad=True) + + torch_tensor_unsqueeze.to(self.device) + torch_result_unsqueeze_0 = torch_tensor_unsqueeze.unsqueeze(0).sum() torch_result_unsqueeze_0.backward() torch_tensor_grad_unsqueeze_0 = torch_tensor_unsqueeze.grad @@ -848,7 +967,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_unsqueeze_1.backward() norch_tensor_grad_unsqueeze_1 = utils.to_torch(norch_tensor_unsqueeze.grad).to(self.device) - torch_tensor_unsqueeze = torch.tensor([[1., 2.], [3, 4]], requires_grad=True).to(self.device) + torch_tensor_unsqueeze = torch.tensor([[1., 2.], [3, 4]], requires_grad=True) + + torch_tensor_unsqueeze.to(self.device) + torch_result_unsqueeze_1 = torch_tensor_unsqueeze.unsqueeze(1).sum() torch_result_unsqueeze_1.backward() torch_tensor_grad_unsqueeze_1 = torch_tensor_unsqueeze.grad @@ -861,7 +983,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_unsqueeze_2.backward() norch_tensor_grad_unsqueeze_2 = utils.to_torch(norch_tensor_unsqueeze.grad).to(self.device) - torch_tensor_unsqueeze = torch.tensor([[1., 2], [3, 4]], requires_grad=True).to(self.device) + torch_tensor_unsqueeze = torch.tensor([[1., 2], [3, 4]], requires_grad=True) + + torch_tensor_unsqueeze.to(self.device) + torch_result_unsqueeze_2 = torch_tensor_unsqueeze.unsqueeze(2).sum() torch_result_unsqueeze_2.backward() torch_tensor_grad_unsqueeze_2 = torch_tensor_unsqueeze.grad @@ -881,8 +1006,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor_grad_unsqueeze_matmul1 = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor_grad_unsqueeze_matmul2 = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32, requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32, requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32, requires_grad=True) + torch_tensor2 = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32, requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result_unsqueeze_matmul = (torch_tensor1 @ torch_tensor2.unsqueeze(0)).sum() torch_result_unsqueeze_matmul.backward() @@ -902,7 +1030,10 @@ class TestTensorAutograd(unittest.TestCase): norch_result_squeeze_0.backward() norch_tensor_grad_squeeze_0 = utils.to_torch(norch_tensor_squeeze.grad).to(self.device) - torch_tensor_squeeze = torch.tensor([[[1., 2], [3, 4]]], requires_grad=True).to(self.device) + torch_tensor_squeeze = torch.tensor([[[1., 2], [3, 4]]], requires_grad=True) + + torch_tensor_squeeze.to(self.device) + torch_result_squeeze_0 = torch_tensor_squeeze.squeeze(0).sum() torch_result_squeeze_0.backward() torch_tensor_grad_squeeze_0 = torch_tensor_squeeze.grad @@ -922,8 +1053,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor_grad_squeeze_matmul1 = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor_grad_squeeze_matmul2 = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[[1., 2], [3, 4]]], dtype=torch.float32, requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[[1., 2], [3, 4]]], dtype=torch.float32, requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[[1., 2], [3, 4]]], dtype=torch.float32, requires_grad=True) + torch_tensor2 = torch.tensor([[[1., 2], [3, 4]]], dtype=torch.float32, requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result_squeeze_matmul = (torch_tensor1.squeeze(0) @ torch_tensor2).sum() torch_result_squeeze_matmul.backward() @@ -946,8 +1080,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor_grad_T_matmul1 = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor_grad_T_matmult2 = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[1, 2.1], [3, -4], [5, 6], [7, 8]], dtype=torch.float32, requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[1, 5.1], [0.1, -4], [0, 6], [7, 8]], dtype=torch.float32, requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[1, 2.1], [3, -4], [5, 6], [7, 8]], dtype=torch.float32, requires_grad=True) + torch_tensor2 = torch.tensor([[1, 5.1], [0.1, -4], [0, 6], [7, 8]], dtype=torch.float32, requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result_T_matmul = (torch_tensor1.T @ torch_tensor2).sum() torch_result_T_matmul.backward() @@ -962,7 +1099,7 @@ class TestTensorAutograd(unittest.TestCase): The code has a problem on the following operation tensor1.reshape(..) @ tensor1 print(tensor1.grad) - (also transpsoe and .T) + (also transpose and .T) """ pass @@ -978,8 +1115,11 @@ class TestTensorAutograd(unittest.TestCase): norch_tensor_grad_transpose_matmul1 = utils.to_torch(norch_tensor1.grad).to(self.device) norch_tensor_grad_transpose_matmult2 = utils.to_torch(norch_tensor2.grad).to(self.device) - torch_tensor1 = torch.tensor([[1, 2.1], [3, -4], [5, 6], [7, 8]], dtype=torch.float32, requires_grad=True).to(self.device) - torch_tensor2 = torch.tensor([[1, 5.1], [0.1, -4], [0, 6], [7, 8]], dtype=torch.float32, requires_grad=True).to(self.device) + torch_tensor1 = torch.tensor([[1, 2.1], [3, -4], [5, 6], [7, 8]], dtype=torch.float32, requires_grad=True) + torch_tensor2 = torch.tensor([[1, 5.1], [0.1, -4], [0, 6], [7, 8]], dtype=torch.float32, requires_grad=True) + + torch_tensor1.to(self.device) + torch_tensor2.to(self.device) torch_result_transpose_matmul = (torch_tensor1.T @ torch_tensor2).sum() torch_result_transpose_matmul.backward() From 5946e6e1bd692476e1af66db1e1d52028d818cf6 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 23 May 2024 03:01:27 -0300 Subject: [PATCH 14/14] fix unittest test nn cuda --- tests/test_nn.py | 75 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/tests/test_nn.py b/tests/test_nn.py index cd623f3..4896506 100644 --- a/tests/test_nn.py +++ b/tests/test_nn.py @@ -26,8 +26,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_norch = loss_fn_norch.forward(predictions_norch, labels_norch) loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([[1.1, 2, 3, 4], [1.1, 2, 3, 4]]).to(self.device) - labels_torch = torch.tensor([[1.1, 2, 3, 4], [1.1, 2, 3, 3]]).to(self.device) + predictions_torch = torch.tensor([[1.1, 2, 3, 4], [1.1, 2, 3, 4]]) + labels_torch = torch.tensor([[1.1, 2, 3, 4], [1.1, 2, 3, 3]]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -38,8 +42,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_norch = loss_fn_norch.forward(predictions_norch, labels_norch) loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([1.1, 2, 3, 4]).to(self.device) - labels_torch = torch.tensor([4, 3, 2.1, 1]).to(self.device) + predictions_torch = torch.tensor([1.1, 2, 3, 4]) + labels_torch = torch.tensor([4, 3, 2.1, 1]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -58,8 +66,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([2.0, 1.0, 0.1]).to(self.device) - labels_torch = torch.tensor(0).to(self.device) + predictions_torch = torch.tensor([2.0, 1.0, 0.1]) + labels_torch = torch.tensor(0) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -71,8 +83,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([[0.5, 1.5, 2.5], [1.0, 2.0, 3.0]]).to(self.device) - labels_torch = torch.tensor([2, 1]).to(self.device) + predictions_torch = torch.tensor([[0.5, 1.5, 2.5], [1.0, 2.0, 3.0]]) + labels_torch = torch.tensor([2, 1]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -83,8 +99,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_norch = loss_fn_norch.forward(predictions_norch, labels_norch) loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]).to(self.device) - labels_torch = torch.tensor([1, 2]).to(self.device) + predictions_torch = torch.tensor([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]) + labels_torch = torch.tensor([1, 2]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -95,8 +115,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_norch = loss_fn_norch.forward(predictions_norch, labels_norch) loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([0.5, 0.2, 0.1]).to(self.device) - labels_torch = torch.tensor([1., 0, 0]).to(self.device) + predictions_torch = torch.tensor([0.5, 0.2, 0.1]) + labels_torch = torch.tensor([1., 0, 0]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -107,8 +131,12 @@ class TestNNModuleLoss(unittest.TestCase): loss_norch = loss_fn_norch.forward(predictions_norch, labels_norch) loss_torch_result = utils.to_torch(loss_norch).to(self.device) - predictions_torch = torch.tensor([[0.5, 0.2, 0.1], [0.1, 0.5, 0.7]]).to(self.device) - labels_torch = torch.tensor([[1., 0, 0], [0, 1, 0]]).to(self.device) + predictions_torch = torch.tensor([[0.5, 0.2, 0.1], [0.1, 0.5, 0.7]]) + labels_torch = torch.tensor([[1., 0, 0], [0, 1, 0]]) + + predictions_torch.to(self.device) + labels_torch.to(self.device) + loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) @@ -133,7 +161,10 @@ class TestNNModuleActivationFn(unittest.TestCase): sigmoid_norch = sigmoid_fn_norch.forward(x) sigmoid_torch_result = utils.to_torch(sigmoid_norch).to(self.device) - x = torch.tensor([[1, 2, 3]]).to(self.device) + x = torch.tensor([[1, 2, 3]]) + + x.to(self.device) + sigmoid_torch_expected = sigmoid_fn_torch.forward(x) self.assertTrue(utils.compare_torch(sigmoid_torch_result, sigmoid_torch_expected)) @@ -143,7 +174,10 @@ class TestNNModuleActivationFn(unittest.TestCase): sigmoid_norch = sigmoid_fn_norch.forward(x) sigmoid_torch_result = utils.to_torch(sigmoid_norch).to(self.device) - x = torch.tensor([-1, 2, -3]).to(self.device) + x = torch.tensor([-1, 2, -3]) + + x.to(self.device) + sigmoid_torch_expected = sigmoid_fn_torch.forward(x) self.assertTrue(utils.compare_torch(sigmoid_torch_result, sigmoid_torch_expected)) @@ -153,7 +187,10 @@ class TestNNModuleActivationFn(unittest.TestCase): sigmoid_norch = sigmoid_fn_norch.forward(x) sigmoid_torch_result = utils.to_torch(sigmoid_norch).to(self.device) - x = torch.tensor([0, 0, 0]).to(self.device) + x = torch.tensor([0, 0, 0]) + + x.to(self.device) + sigmoid_torch_expected = sigmoid_fn_torch.forward(x) self.assertTrue(utils.compare_torch(sigmoid_torch_result, sigmoid_torch_expected)) @@ -180,7 +217,9 @@ class TestNNModuleActivationFn(unittest.TestCase): for norch_input, torch_input in test_cases: # Move tensors to the correct device norch_input = norch_input.to(self.device) - torch_input = torch_input.to(self.device) + torch_input = torch_input + + torch_input.to(self.device) # Forward pass using norch softmax_norch = softmax_fn_norch.forward(norch_input)