From 769666cfa82f6877404077abc2da9ee87f3ef603 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Wed, 1 May 2024 12:11:50 -0300 Subject: [PATCH] Reshape autograd --- build/cpu.o | Bin 4024 -> 4232 bytes build/cuda.cu.o | Bin 58576 -> 62224 bytes build/libtensor.so | Bin 85808 -> 90272 bytes build/tensor.o | Bin 22600 -> 22984 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 8844 -> 8960 bytes .../__pycache__/functions.cpython-38.pyc | Bin 3072 -> 3473 bytes norch/autograd/functions.py | 9 +++- norch/csrc/cpu.cpp | 7 +++ norch/csrc/cpu.h | 1 + norch/csrc/cuda.cu | 22 +++++++++ norch/csrc/cuda.h | 4 ++ norch/csrc/tensor.cpp | 45 +++++++++--------- norch/csrc/tensor.h | 2 +- norch/tensor.py | 19 +++++--- test.py | 9 ++-- 15 files changed, 83 insertions(+), 35 deletions(-) diff --git a/build/cpu.o b/build/cpu.o index 1805e130007d4ae4c6ce5dc57c4690b0aaa1dd3e..e34690093b3e826c7c79167354e0ba47272fffe6 100644 GIT binary patch delta 319 zcmdlX-=R1`gNcK8qn0u2WE~bIb2E=_*B2h$4BerBJd!VY9DKy&!FZ_K^^eC4k6xZu z1|R?`c;LZ!;xoSh(`SA`hGy44jIZ}ij$$=q21;)3XN_fKl$rdNOKFZKMvA8%h zJ#VrDm)PdHT*{0>DNy5>fXYBvmUZ$j?t6@tlV|dnGevMuzQkk4xO1`~uRV|q1d@9u zPXv+&CSL@SZzc=!*)x8a9LQ(SDZmD@h=HMD@=QK+t`2SpkArdYEj}~O3G5KA#$-u; abIu){5Z>I$k^JUd6L=uJ5{AjMc;o;H6ia9T delta 172 zcmeBB+#x?fgUNztqn0u2n?JC|FfuAk_GOo!EX*sjc?J6q#?3o8YZ*6(aw{`V zp1^a1QFd}BuQ}5KuE~pd?HFSxKjgIsl8Suxj0uwyfn>_$g+Ow`8$k11kd< zBuviaH|M&*1>t>Qn7oSLj8lLe!WEeOlHZ(DffK^3ovbNf&UJtr!Yg5zoW&~#0G<;n A+W-In diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 99d9f0fa5f492b85a3fef8205868978b48cef51b..a9d57ca942870e2b1955b15156ca925ccae9d0c8 100644 GIT binary patch delta 12199 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 delta 10607 zcmZ{q3s_V~mVoWyt&-EX?fSm1 zd+R@^&N+3eZgusA#=iu0oDOPCQcJ&TO&QtWQ$3(cQJ)Nl#+Xb+g=R+{^cy@JUJd(R z-RFQcj!boh!*kFvNl|0NwB{W<9CT!QD#J%9>V^T-O)VaPDA&_(aF(K8v}x$KHbQ7B z!*j=J#?Dp^-|2@q+p{cklcFYCpl3*?+7qhToB!B6MO|#xw1%5Ct%RuIiuy?(&1*v+ zL`%UP_IEWsL?izf>>28+R@C1FX?;qAP@w?Kv59apE+RPQ>jw`!W%1c6Tp#u%Y)KfV zh|4EEiAuOdCE~G>{cCRsMMKvi(KHe=~0zala6?Obs9h>Iq z*J&ZsO!=lPQxMjpVCC>!cyCNRgpXP5xjEvqzMhkrP9>zea#iI@*mpAN@YwYh_tV%h z$P^{a^j-!l#2vjr-2J1*hx+j`D(MgOr4GY< z1=!l9@gaWvy2cay_y!BvdCZS@YCO@8zueDciV8A4?k6~af*=#-6)Lw4bUW<5tD_cY zpUNz}I_zu}2>t@jw!_Y5TkuzLQXO`e)>o@=2vlA|Ck}gz-oU!HzkXYfljN{#lO$$H z7X$jt9ZCZNexTvTQrX|v3raSsAip;6+wS$;MIv+mS7Sj4jU47QynN6PXEWko5>w z3SnEKl>@}o{8%X7lAz>4M!hq1U#xDZ1|>u>JydkA)_I}ES~>$(1~u}gPI0s=!j(9)aww|5Us3(R%9(HI$H;2 z$esdkgHss+bq$G%12VQ^UQ?yK6Xh)$i%-*86@+b#R^~t}>NTe8Y&Dc2Q^C6xgV~x0 z)!T55jnZXu=cQ@Ib!D#A@x%J>P_r!}DO0q?cu5(bygs!L)$|*jrfp8uGzKXokF&4=PKKvW(Q_wp5BSqv_kD1;Qef94WLa+)TliOygP8p=E3G23Cda7 zID?H}Lk(yW3nVB-(5g3zu@MCsJM});xG5WFuu%s!y2P?GLBX#xy-|#fPi15C&IG7_ z)2tqU7Agw{L*tt|oUThw! zrmJx9V1nAC!dFd0m9=ocDN)ISVa?IXaaf7>wXm`|S~UkzAEk{Np`|pzSY83|y91%8 z*{ay#K6cm*Q3n&1a+q{5I`q1q&OS{i37QWks<(nQZ`E1@&-Uc{DC8VUEL@9+6e?Oi zCiS^+Q6S9)w*!VAaNX$=adZ0v5ISUTz@#zx>aqC^ZerQU?uiHagQf_luTjK9OAWG@VRkt z!1IP;gN!4Kl*eKF5vMX-tFz$*-p>Lr*2}f}C9Qr{t2b(Oy;cL&(6c!hzC98i`7RyL z&|wJ8IhGFnVmhg5mA)68O43h-)FrN6*egcuUD$HrghK0k&d6c7cBt2-0lG1{l}#Zj z&J@+Zgp6ZOtK-6CpK=sb3<;DEQlA zcI4Pc&>0*(h7Hs`N^8#veq79g3EtW2WjHBmF%!W z@EannGSEK?zE&hu@*9F%#rcVT8&iqH6!tE2$USCJvbB{vORHCE^=hi2@mRl*(My+R zEcWa>Ru}A9@$c^jd&)n#uEMHQOW^ZU@yZi$|CAGcK4k@0TYThbwEpu0y)eIgVhl@v!ETlp6X=fxIaHRbzCe49sXyfW>t8Evfd0;!^1nU_qq@VG%e2Qrm zz)IArI%BonW^@AVIpd7XV*W;ntz3_$9i=>))l8ZL_fa~T^}WfYX^?u>x9>1AiG?mX zumGh~@J^0%A(Q4o!&xWPpS42ES>F+DV_F5!g<5ydT5X3Jod8kioRJfl<±tlou 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 delta 21806 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 Q*;viIZl5kH(5g582kI+|5dZ)H delta 1942 zcmZ{kU1%It6vywKm`}IOrZl;oxJkOzmf9{&7t?$+;5L>E6XVvMW;br$8jIM1q5+XU zSW5_vE<>T=ywsQ4JSZB_Hq474K@*fjh_p4OwDcpUpcGRukyZ1srJg%;M-BtIFn78C z-#Pz#?wPwY@ACO8{QPcXK0CGN%(n5qNW+|b#2I6AausLh$klGSaC#?H8ry5-DqmT& z9C^z*l<1O=;C-_dM!1OHvI?1~(k)h6}O2pV} z*13ogVd8+hLEJnxfSTGbo6iE6Jp;yDcCX<-7PTL}HyqqCasL9&_9+pv}v z{66rsNIoPEbl*QW$gKeTh%ldi2JLXDs%r5GPFfFfq;F~(bnl`H#qkbI9TB}ia+^>M zaz7_}8_}nUUPE;3+pEI-UDNOxAA5Bg`g(=yjKDDFwh(%NIJd(D(mp~3p&!6?q#qMX z-}NN$j4*%PfZm2=M(|bWL5IId4DI0)RU5B>ar9|Y4Z;z0GU6}U4j4k3&@_AxKZG@; zV}#aYUeM=Bh}*)PCbWal8(KJIRh|qSN>L zI@BG-8%`*_|DQq+(iuYO{lBXy_Ibn>yb>lbGScF=E_@Rj;5yPKO~bdS&CBiDAosAB z`QL&jVJav13HT|u#6N;B2Rdpp`xR&G z$`1HrpqTFfzSCg+@F4$U^}D-#hfDDM YU`KT{;jg;jV-H0&1YdC{Yd?kQHFWfQ4qd1WmRP zgo7sd5nsF#NQ@^nF?-fTLt;XL@nAe~;c6r%nwaRpgEI>x%w~S?&Ahks-hXyi&MlmG zXI(BuV5507Ir*jQjr$kC_orgc*I95C+{=(t3u?i$EaW_e1Wt>KkTiaXNeOZov;W0S zTNX=>Cj6{Oo_2N!wR7MvV#>$;^XY0{EVm32v%iK4@rb6sFw&E6r*bLqmAn^`xr zDzmCC(lyPa3rnC2q*fP31R7+OTfO*D8NeqF1+!80xSB3jZsyCyv-yeX`8+MqD9^Fc zW@d7Znc_S#!!*LyxU0nFPUg^rsWR+zMZ#<;h+c4uG4Oy_ltBiCJ$BI!R_t}|!d>G? z%_2xAS>6MD>ADZAMvt2StQ*hNqoOp#_Fv4sDQ|7^pKYF;?6~7%eF%{^*4gWtg{nUP{ z7d-(LMz|ygFEuw#$c~W;^oh`pw}X=`c_)~WGrVpBw_-t_Rhqj+$ZyQmFSxFZiVa+H@=26kW)O<#>7Oh6z<>a z3g3mD&|++cTYz;m9QC8Mq3w`1-cNaUo{)ZHq@fAG{0AjVWv-OQ$I%VQV-EH62egS-46DR6D8SS<(QJ1O9czN_@+HhW6ft2-AY?qW>Z($)@Vslq! zF`kHG+Vu(C_}tmVjNlp9Z9$lS@XD z;3AL}qYYO>ethQc4U2rZ-)eXw@!rRKsfb=BkP}T|15B|Dx1a*o9em_4YbszzAOs($4GwyreuLoZ$eG%IyS!}H_T6man zFJzZkX=bXJ#eP*sLygvZxh{x4(8M?>;1gwhqJD>~)_Uy=Tf}b!*2ypB=87r9vW1INfH!Kg6-eX_Uq~8s%tQmhDz%hIs zjp6-31d_NN=#W!X)y}IzYe5O#;8rM!UBN$lb%UX5T>x){>S2_ZMc}iw73vZB@^6hf zUN+P;s*c&45K^?0Jij={*bjWywCuUS)mG8I3S-PRGaGh85EsK~^(3vBB#_OJypWw{ ztP#J2(@+(Pg%V>CD;+V(_=_mBE%-4RQ=!@Fi5&!PW2*VYf2WX(g(b$it)1or0QL_e zIZBK3r`O^;a0%bWJNHi3kT_hOcEIQb98YxNYGNSUL1sD$U4(7|J&4guI8Lyyb%e6B xgmVNsq`?Rm2~&j2gbX3evFj=tg<{q)uNgV~pf}*S9u-|0F6l>L8XxKB{{cO|(K7%5 diff --git a/norch/autograd/__pycache__/functions.cpython-38.pyc b/norch/autograd/__pycache__/functions.cpython-38.pyc index c6788342746a38061e394c16abfe0fd5e759dcb8..615f47296adea2d2758e16b46d21375e20418144 100644 GIT binary patch delta 285 zcmZpWm?+H`%FD~e00fy24bzO-Ci2NJmQ2)66>(=s;Y;CfVMyU`W{P4@5eR0`6r7yT zVYl(hI!?}&Ohs%!Ek*2;899U}&*MsETsfJAd-3EaY_=TyL8-+Vi3O>X-MDO+isV2l zB)EZ!ErGb02}m$7R!P9r2(oFLhyaCZ7#A?qFk~^NFiJ9HF)d_FXAEX2k_Sp?GT&k^ zf*4rD0_5Lfg&3Z|EGc3G4Ca>aFVN{*$$RVzH di^C>2KczG$)s7LQk`GAmu>&Co5OV=Z4giC9JM#bl delta 87 zcmbOz-5|ji%FD~e00gJb8K!lzPUMqeOq-~k%9g?x%%I6XIg!size; i++) { + result_data[i] = tensor->data[i]; + } +} diff --git a/norch/csrc/cpu.h b/norch/csrc/cpu.h index e1e3744..f50b0d9 100644 --- a/norch/csrc/cpu.h +++ b/norch/csrc/cpu.h @@ -13,5 +13,6 @@ void scalar_mul_tensor_cpu(Tensor* tensor, float scalar, 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_tensor_cpu(Tensor* tensor, float* result_data); +void assign_tensor_cpu(Tensor* tensor, float* result_data); #endif /* CPU_H */ diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index df810eb..11574cb 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -314,4 +314,26 @@ __host__ void transpose_tensor_cuda(Tensor* tensor, float* result_data) { cudaDeviceSynchronize(); } +__global__ void assign_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 assign_tensor_cuda(Tensor* tensor, float* result_data) { + + int number_of_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + assign_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(); +} + diff --git a/norch/csrc/cuda.h b/norch/csrc/cuda.h index 606fb70..7825534 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -34,6 +34,10 @@ __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 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 4f7d765..edccaba 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -425,7 +425,15 @@ extern "C" { } } - void reshape_tensor(Tensor* tensor, int* new_shape, int new_ndim) { + Tensor* reshape_tensor(Tensor* tensor, int* new_shape, int new_ndim) { + char* device = (char*)malloc(strlen(tensor->device) + 1); + if (device != NULL) { + strcpy(device, tensor->device); + } else { + fprintf(stderr, "Memory allocation failed\n"); + exit(-1); + } + // Calculate the total number of elements in the new shape int new_size = 1; for (int i = 0; i < new_ndim; i++) { @@ -438,28 +446,21 @@ extern "C" { exit(1); } - // Update the shape - tensor->shape = (int*)malloc(new_ndim * sizeof(int)); - if (tensor->shape == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); - } - for (int i = 0; i < new_ndim; i++) { - tensor->shape[i] = new_shape[i]; - } - tensor->ndim = new_ndim; + if (strcmp(tensor->device, "cuda") == 0) { - // Update the strides - tensor->strides = (int*)malloc(new_ndim * sizeof(int)); - if (tensor->strides == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); - } - - int stride = 1; - for (int i = new_ndim - 1; i >= 0; i--) { - tensor->strides[i] = stride; - stride *= new_shape[i]; + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + assign_tensor_cuda(tensor, result_data); + return create_tensor(result_data, new_shape, new_ndim, device); + } + else { + float* result_data = (float*)malloc(tensor->size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + assign_tensor_cpu(tensor, result_data); + return create_tensor(result_data, new_shape, new_ndim, device); } } diff --git a/norch/csrc/tensor.h b/norch/csrc/tensor.h index 77ae341..d59cf69 100644 --- a/norch/csrc/tensor.h +++ b/norch/csrc/tensor.h @@ -22,7 +22,7 @@ extern "C" { Tensor* sub_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* elementwise_mul_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* scalar_mul_tensor(Tensor* tensor, float scalar); - void reshape_tensor(Tensor* tensor, int* new_shape, int new_ndim); + Tensor* reshape_tensor(Tensor* tensor, int* new_shape, int new_ndim); Tensor* matmul_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* pow_tensor(Tensor* tensor, float power); void to_device(Tensor* tensor, char* device); diff --git a/norch/tensor.py b/norch/tensor.py index 74be89f..94568e1 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -93,7 +93,7 @@ class Tensor: Tensor._C.zeros_like_tensor.restype = ctypes.POINTER(CTensor) Tensor._C.zeros_like_tensor(self.tensor) - result_tensor_ptr = Tensor._C.ones_like_tensor(self.tensor) + result_tensor_ptr = Tensor._C.zeros_like_tensor(self.tensor) result_data = Tensor() result_data.tensor = result_tensor_ptr @@ -103,17 +103,24 @@ class Tensor: return result_data - def reshape(self, new_shape): + def reshape(self, new_shape, requires_grad=None): new_shape_ctype = (ctypes.c_int * len(new_shape))(*new_shape) new_ndim_ctype = ctypes.c_int(len(new_shape)) Tensor._C.reshape_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.POINTER(ctypes.c_int), ctypes.c_int] - Tensor._C.reshape_tensor.restype = None - Tensor._C.reshape_tensor(self.tensor, new_shape_ctype, new_ndim_ctype) + Tensor._C.reshape_tensor.restype = ctypes.POINTER(CTensor) + result_tensor_ptr = Tensor._C.reshape_tensor(self.tensor, new_shape_ctype, new_ndim_ctype) - self.shape = new_shape - self.ndim = len(new_shape) + result_data = Tensor() + result_data.tensor = result_tensor_ptr + result_data.shape = new_shape.copy() + result_data.ndim = len(new_shape) + result_data.device = self.device + + result_data.requires_grad = self.requires_grad + if requires_grad: + self.grad_fn = ReshapeBackward(self) return self diff --git a/test.py b/test.py index 56813ba..8cff585 100644 --- a/test.py +++ b/test.py @@ -30,12 +30,11 @@ if __name__ == "__main__": a = norch.Tensor([[1, 2], [1, 2], [1, 2]], requires_grad=True)#.to("cuda") b = norch.Tensor([[1, 400, 3], [1, 2, 3]], requires_grad=True) - print(a.sum()) - #c = (b @ a) * 5 - #d = c.sum() - #d.backward() + c = (a@b).reshape([9]) + d = c.sum() + d.backward() - #print(a.grad) + print(a.grad) """#print(a) N = 1000