From cc483417dc2c3a09a95786e537010f454c745993 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Mon, 20 May 2024 12:50:45 -0300 Subject: [PATCH] max min and equal operations --- build/cpu.o | Bin 10848 -> 13776 bytes build/cuda.cu.o | Bin 130552 -> 134232 bytes build/tensor.o | Bin 43304 -> 48712 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 16110 -> 17577 bytes .../__pycache__/functions.cpython-38.pyc | Bin 8173 -> 8929 bytes norch/autograd/functions.py | 18 ++ norch/csrc/cpu.cpp | 68 +++++++ norch/csrc/cpu.h | 3 + norch/csrc/cuda.cu | 22 +++ norch/csrc/cuda.h | 3 + norch/csrc/tensor.cpp | 184 +++++++++++++++++- norch/csrc/tensor.h | 3 + norch/libtensor.so | Bin 172864 -> 181968 bytes norch/nn/__init__.py | 3 +- norch/nn/__pycache__/__init__.cpython-38.pyc | Bin 215 -> 241 bytes .../nn/__pycache__/activation.cpython-38.pyc | Bin 1170 -> 1201 bytes norch/nn/activation.py | 3 +- norch/nn/functional.py | 5 + norch/tensor.py | 93 +++++++++ test.py | 9 +- tests/test_autograd.py | 38 +++- tests/test_operations.py | 99 +++++++++- 22 files changed, 543 insertions(+), 8 deletions(-) create mode 100644 norch/nn/functional.py diff --git a/build/cpu.o b/build/cpu.o index 6372b93e473468016bdccce213ac77d7ba4524e3..3299b62bd1e95cbf0cb55b237c31bd7fe046c036 100644 GIT binary patch literal 13776 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 O*fYX^AI2fyY5fmBLsPu~ diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 7f95837f611145b07fe527f2322a17c89d8456d2..cb40e3902554ad0a536216247e5433cfc59de8e9 100644 GIT binary patch delta 25163 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 F{{y-pCP@GQ diff --git a/build/tensor.o b/build/tensor.o index 893104690408c2422c28c7d106ccbeac4d8628d0..53ef71001ad06f64757a2dae640d22bbfe9bacc7 100644 GIT binary patch literal 48712 zcmeI54}4VBmB-%%tbwA$R$COb<9|eqNdN&sjmU!$0jZLzENvK)38dzqnMpyHsNEoS z9O=5!?pBL`ck8NUSGrQgiW>gdgq3yEN-eACX1m%#gOw`v-)h-&?mK7Z_wKxx0M>rC z+uYA5%*^-R_q*qud+vL0?tAmN!JRp+AQEx3M4a=T+$W`u)A^&^`*QQP+&R)Y!g+h> z2_IC%(yzzb_LRrctvh1rmacTgwpe;r`!f@$-7an$OS|vI+FIXpTF#1P4l^V}aO01T zrT0&Bcd?b{F*dEAVc>0-q3tpiBw7^n-gd>(bIkip#kTaEkwn{L=?<@PTYDt?KE26o zke*XQ{kA))GrjH0OGu8kcrn|MWIM`7bB`VF9yX!pfK1#^#q^qS_e^rPwbDlJdzm?- z>0|6Wv6Vw^Vku%>u}Eje8Tv>U*Qe)$@B58MDTkAe&=>@8nsn{2*`e|(AFA8FjO&ND@x*+53V_S~~Te~t®2V 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 MNa=?1YRCV70W9R`W&i*H literal 43304 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 delta 343 zcmaFp`qrK=l$V!_0SMwgdZeuvo5&}_^oC)g&MTf2#$X0brI#QnzsZWsQj_($ls8v1 z$_fc-G8eG|MT?|Bgba|-+`LLSlZnxGvxrzOBey$97_2~ivOK%Y5Gf>h=*bB&=55zE?tVLd6 zozEnH3i|@ZS0KqT7x{wZHXBLXGqU;vB{occBIURFh>QxOZ~&0I3q@@JP_5%+8@a=b zL6awni%%Apx0474syKwA3M8T_IN4muLJH)GB9MEEKo%E)EGPmQTNFI`0#N@dC4NSQ I$-9)40eKck8UO$Q diff --git a/norch/autograd/functions.py b/norch/autograd/functions.py index 74594fe..b862b73 100644 --- a/norch/autograd/functions.py +++ b/norch/autograd/functions.py @@ -198,5 +198,23 @@ class CosBackward: def backward(self, gradient): x = self.input[0] return [-gradient * x.sin()] + +class MaxBackward: + def __init__(self, x, axis=None, keepdim=False): + self.input = [x] + self.axis = axis + self.keepdim = keepdim + + def backward(self, gradient): + pass + +class MinBackward: + def __init__(self, x, axis=None, keepdim=False): + self.input = [x] + self.axis = axis + self.keepdim = keepdim + + def backward(self, gradient): + pass diff --git a/norch/csrc/cpu.cpp b/norch/csrc/cpu.cpp index c308d58..6d65273 100644 --- a/norch/csrc/cpu.cpp +++ b/norch/csrc/cpu.cpp @@ -235,8 +235,76 @@ void sum_tensor_cpu(Tensor* tensor, float* result_data, int size, int* result_sh } } +void max_tensor_cpu(Tensor* tensor, float* result_data, int size, int* result_shape, int axis) { + if (axis == -1) { + float max_value = -INFINITY; + for (int i = 0; i < tensor->size; i++) { + max_value = fmax(max_value, tensor->data[i]); + } + *result_data = max_value; + } else { + for (int i = 0; i < size; i++) { + result_data[i] = -INFINITY; + } + if (axis < 0 || axis >= tensor->ndim) { + printf("Invalid axis"); + return; + } + + int axis_stride = tensor->strides[axis]; + for (int i = 0; i < tensor->shape[axis]; i++) { + for (int j = 0; j < size; j++) { + int index = 0; + int remainder = j; + for (int k = tensor->ndim - 2; k >= 0; k--) { + index += (remainder % result_shape[k]) * tensor->strides[k < axis ? k : k + 1]; + remainder /= result_shape[k]; + } + result_data[j] = fmax(result_data[j], tensor->data[index + i * axis_stride]); + } + } + } +} +void min_tensor_cpu(Tensor* tensor, float* result_data, int size, int* result_shape, int axis) { + if (axis == -1) { + float min_value = INFINITY; + for (int i = 0; i < tensor->size; i++) { + min_value = fmin(min_value, tensor->data[i]); + } + *result_data = min_value; + } else { + for (int i = 0; i < size; i++) { + result_data[i] = INFINITY; + } + if (axis < 0 || axis >= tensor->ndim) { + printf("Invalid axis"); + return; + } + + int axis_stride = tensor->strides[axis]; + + for (int i = 0; i < tensor->shape[axis]; i++) { + for (int j = 0; j < size; j++) { + int index = 0; + int remainder = j; + for (int k = tensor->ndim - 2; k >= 0; k--) { + index += (remainder % result_shape[k]) * tensor->strides[k < axis ? k : k + 1]; + remainder /= result_shape[k]; + } + result_data[j] = fmin(result_data[j], tensor->data[index + i * axis_stride]); + } + } + } +} + +void equal_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data) { + + for (int i = 0; i < tensor1->size; i++) { + result_data[i] = (tensor1->data[i] == tensor2->data[i]) ? 1.0f : 0.0f; + } +} void ones_like_tensor_cpu(Tensor* tensor, float* result_data) { diff --git a/norch/csrc/cpu.h b/norch/csrc/cpu.h index 28404e5..b006ca7 100644 --- a/norch/csrc/cpu.h +++ b/norch/csrc/cpu.h @@ -6,6 +6,8 @@ void add_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data); void add_broadcasted_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data, int* broadcasted_shape, int broadcasted_size); void sum_tensor_cpu(Tensor* tensor, float* result_data, int size, int* shape, int axis); +void max_tensor_cpu(Tensor* tensor, float* result_data, int size, int* result_shape, int axis); +void min_tensor_cpu(Tensor* tensor, float* result_data, int size, int* result_shape, int axis); void sub_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data); void sub_broadcasted_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data, int* broadcasted_shape, int broadcasted_size); void elementwise_mul_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data); @@ -19,6 +21,7 @@ void scalar_pow_tensor_cpu(float base, Tensor* tensor, float* result_data); void tensor_pow_scalar_cpu(Tensor* tensor, float exponent, float* result_data); void log_tensor_cpu(Tensor* tensor, float* result_data); void scalar_mul_tensor_cpu(Tensor* tensor, float scalar, float* result_data); +void equal_tensor_cpu(Tensor* tensor1, Tensor* tensor2, float* result_data); void ones_like_tensor_cpu(Tensor* tensor, float* result_data); void zeros_like_tensor_cpu(Tensor* tensor, float* result_data); void transpose_1D_tensor_cpu(Tensor* tensor, float* result_data); diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 467b8cc..5726c69 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -542,6 +542,28 @@ __host__ void log_tensor_cuda(Tensor* tensor, float* result_data) { cudaDeviceSynchronize(); } +__global__ void equal_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size) { + + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < size) { + result_data[i] = (data1[i] == data2[i]) ? 1.0f : 0.0f; + } +} + +__host__ void equal_tensor_cuda(Tensor* tensor1, Tensor* tensor2, float* result_data) { + + int number_of_blocks = (tensor1->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + equal_tensor_cuda_kernel<<>>(tensor1->data, tensor2->data, result_data, tensor1->size); + + cudaError_t error = cudaGetLastError(); + if (error != cudaSuccess) { + printf("CUDA error: %s\n", cudaGetErrorString(error)); + exit(-1); + } + + cudaDeviceSynchronize(); +} + __global__ void ones_like_tensor_cuda_kernel(float* data, float* result_data, int size) { diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index f7a883b..712e600 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -49,6 +49,9 @@ __global__ void log_tensor_cuda_kernel(float* data, float* result_data, int size); __host__ void log_tensor_cuda(Tensor* tensor, float* result_data); + __global__ void equal_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size); + __host__ void equal_tensor_cuda(Tensor* tensor1, Tensor* tensor2, float* result_data); + __global__ void ones_like_tensor_cuda_kernel(float* data, float* result_data, int size); __host__ void ones_like_tensor_cuda(Tensor* tensor, float* result_data); diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index b717145..8564b2a 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -173,7 +173,6 @@ extern "C" { } Tensor* sum_tensor(Tensor* tensor, int axis, bool keepdim) { - char* device = (char*)malloc(strlen(tensor->device) + 1); if (device != NULL) { strcpy(device, tensor->device); @@ -211,16 +210,145 @@ extern "C" { float* result_data; cudaMalloc((void**)&result_data, size * sizeof(float)); + cudaMemset(result_data, 0, size * sizeof(float)); sum_tensor_cuda(tensor, result_data); return create_tensor(result_data, shape, ndim, device); } + else { + float* result_data = (float*)calloc(size, sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + sum_tensor_cpu(tensor, result_data, size, shape, axis); + + if (keepdim) { + 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* max_tensor(Tensor* tensor, int axis, bool keepdim) { + char* device = (char*)malloc(strlen(tensor->device) + 1); + if (device != NULL) { + strcpy(device, tensor->device); + } else { + fprintf(stderr, "Memory allocation failed\n"); + exit(-1); + } + int ndim; + int* shape; + if (axis == -1) { + shape = (int*) malloc(sizeof(int)); + if (shape == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + shape[0] = 1; + ndim = 1; + } else { + shape = (int*) malloc((tensor->ndim - 1) * sizeof(int)); + for (int i = 0, j = 0; i < tensor->ndim; ++i) { + if (i != axis) { + shape[j++] = tensor->shape[i]; + } + } + ndim = tensor->ndim - 1; + + } + + int size = 1; + for (int i = 0; i < ndim; i++) { + 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); } - sum_tensor_cpu(tensor, result_data, size, shape, axis); + max_tensor_cpu(tensor, result_data, size, shape, axis); + + if (keepdim) { + 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* min_tensor(Tensor* tensor, int axis, bool keepdim) { + char* device = (char*)malloc(strlen(tensor->device) + 1); + if (device != NULL) { + strcpy(device, tensor->device); + } else { + fprintf(stderr, "Memory allocation failed\n"); + exit(-1); + } + int ndim; + int* shape; + if (axis == -1) { + shape = (int*) malloc(sizeof(int)); + if (shape == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + shape[0] = 1; + ndim = 1; + } else { + shape = (int*) malloc((tensor->ndim - 1) * sizeof(int)); + for (int i = 0, j = 0; i < tensor->ndim; ++i) { + if (i != axis) { + shape[j++] = tensor->shape[i]; + } + } + ndim = tensor->ndim - 1; + + } + + int size = 1; + for (int i = 0; i < ndim; i++) { + 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); + } + min_tensor_cpu(tensor, result_data, size, shape, axis); if (keepdim) { shape = (int*) malloc((tensor->ndim) * sizeof(int)); @@ -905,6 +1033,58 @@ extern "C" { } } + Tensor* equal_tensor(Tensor* tensor1, Tensor* tensor2) { + if (tensor1->ndim != tensor2->ndim) { + fprintf(stderr, "Tensors must have the same number of dimensions %d and %d for equal\n", tensor1->ndim, tensor2->ndim); + exit(1); + } + + if (strcmp(tensor1->device, tensor2->device) != 0) { + fprintf(stderr, "Tensors must be on the same device: %s and %s\n", tensor1->device, tensor2->device); + exit(1); + } + + char* device = (char*)malloc(strlen(tensor1->device) + 1); + if (device != NULL) { + strcpy(device, tensor1->device); + } else { + fprintf(stderr, "Memory allocation failed\n"); + exit(-1); + } + int ndim = tensor1->ndim; + int* shape = (int*)malloc(ndim * sizeof(int)); + if (shape == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + + for (int i = 0; i < ndim; i++) { + if (tensor1->shape[i] != tensor2->shape[i]) { + fprintf(stderr, "Tensors must have the same shape %d and %d at index %d for equal\n", tensor1->shape[i], tensor2->shape[i], i); + exit(1); + } + shape[i] = tensor1->shape[i]; + } + + if (strcmp(tensor1->device, "cuda") == 0) { + + float* result_data; + cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); + equal_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, device); + } + else { + float* result_data = (float*)malloc(tensor1->size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + equal_tensor_cpu(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, device); + } + } + + Tensor* ones_like_tensor(Tensor* tensor) { char* device = (char*)malloc(strlen(tensor->device) + 1); if (device != NULL) { diff --git a/norch/csrc/tensor.h b/norch/csrc/tensor.h index a32e74c..bdcf25d 100644 --- a/norch/csrc/tensor.h +++ b/norch/csrc/tensor.h @@ -17,6 +17,8 @@ extern "C" { float get_item(Tensor* tensor, int* indices); Tensor* add_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* sum_tensor(Tensor* tensor, int axis, bool keepdims); + Tensor* max_tensor(Tensor* tensor, int axis, bool keepdim); + Tensor* min_tensor(Tensor* tensor, int axis, bool keepdim); Tensor* sub_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* elementwise_mul_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* scalar_mul_tensor(Tensor* tensor, float scalar); @@ -28,6 +30,7 @@ extern "C" { Tensor* tensor_pow_scalar(Tensor* tensor, float exponent); Tensor* scalar_pow_tensor(float base, Tensor* tensor); Tensor* log_tensor(Tensor* tensor); + Tensor* equal_tensor(Tensor* tensor1, Tensor* tensor2); void to_device(Tensor* tensor, char* device); Tensor* ones_like_tensor(Tensor* tensor); Tensor* zeros_like_tensor(Tensor* tensor); diff --git a/norch/libtensor.so b/norch/libtensor.so index 9212825f2e434aeeaf8c3bd47dd6fe72c899a152..90f234627e5a99a18bef507126d80646332a50f1 100755 GIT binary patch delta 45489 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

k?Cy=dcch|KubnVuSk0fguT{B&)1UE8Q@zraVc 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 diff --git a/norch/nn/__init__.py b/norch/nn/__init__.py index dadface..8f7997b 100644 --- a/norch/nn/__init__.py +++ b/norch/nn/__init__.py @@ -1,3 +1,4 @@ from .modules import * from .activation import * -from .loss import * \ No newline at end of file +from .loss import * +from .functional import * \ No newline at end of file diff --git a/norch/nn/__pycache__/__init__.cpython-38.pyc b/norch/nn/__pycache__/__init__.cpython-38.pyc index 1f19ab62795fbb5ec30fbec1f63af9cd477f3d17..5b7fd1c7b09471efcfce61414f7fe60ec9c05c2f 100644 GIT binary patch delta 131 zcmcc4_>qw}l$V!_0SI_~ywl<)^2#!*Ow^X~XGmepVGdzPVG3r@WPZsAl-Fdu#i-?{ z$#RQ5H$SB`C$%_=D>1nwvn;VBGe0kiB`3caD3Vs12NcWCOUzlxP{ab%1txwuO>9zQ W52*CZFG|jsxLSpa4JgCG2!a5R3nAtJ delta 88 zcmey!c%6|ql$V!_0SF?wEYn;j^2##GOw^VUVhU!^WPZsA6xU?D#i-?{$viPpROA** kPJVImN`@jjPT{fB7k)HKRhy#CsJ~$!{ z&d&aX^V}R={03FM3EN43T~%H6RejwL{<|L>1VInOHMO(dc)AZJZYtR@X*LXxwHh?Y(+l|TYt zzriNB`UfVaNKXM5D!{V?eH8H;nL3Y@Ea?TSx=uxEkm5nD7AH}j$Mqzs)w-&BDTPXv zgFriX5d_%0#Fe8ztm}CSlr81qVdhXiS*FsoH|5l8Kp*nO3P)=LcTO|5*)v?h3+yx1 zp($W9^z!CWnl+{B$BeFF3=z#ctiSl=%@ExV6O0i2sZpck{wx32FoqYzncD~gPyt2C xqHt65J<3A2V2Vam<7C@u)IK)aO==fwFilD3RmEzje2qRkr#VVc0%7&{{sM&UZ)gAj delta 548 zcmYjO%}T>S5Z>8Mn$#v(ZLxw>dQpg=z4jm~3W|sJp!Cv93E9*tNh6#3hl+x}K#ecr z8wlbol7-}u zw|2>-=18}@T`zFs*z<#++nsVzcZ#e^L!ce!5KPd7C6tzY@%uF$1&1rrvpSSXf0;A8 zKC{zZ#pF?}A5oG$+;JH}f`lPEgF7g&605K!hI8Pp6Aa<{*>-rUh3>GQg0E&#nJO(y zOVyW>U$Oi!Ptg(q