From 6b08c103005129bd2be62db1159de06a4adda61f Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Thu, 9 May 2024 22:32:36 -0300 Subject: [PATCH] Cosine and sine operations with autograd --- build/cpu.o | Bin 7192 -> 7752 bytes build/cuda.cu.o | Bin 87776 -> 100448 bytes build/libtensor.so | Bin 121424 -> 142776 bytes build/tensor.o | Bin 36608 -> 39280 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 13063 -> 13775 bytes .../__pycache__/functions.cpython-38.pyc | Bin 5336 -> 6118 bytes norch/autograd/functions.py | 17 ++++ norch/csrc/cpu.cpp | 12 +++ norch/csrc/cpu.h | 2 + norch/csrc/cuda.cu | 46 +++++++++++ norch/csrc/cuda.h | 5 ++ norch/csrc/tensor.cpp | 75 ++++++++++++++++++ norch/csrc/tensor.h | 2 + norch/tensor.py | 45 ++++++++++- tests/__init__.py | 4 +- tests/test_autograd.py | 34 +++++++- tests/test_nn.py | 16 ++-- tests/test_operations.py | 52 ++++++++++++ 18 files changed, 300 insertions(+), 10 deletions(-) diff --git a/build/cpu.o b/build/cpu.o index 9b48aff98fbcbc203d68fea79ed9a7639f36ee59..4f63638f3a8e25f3daf19c5a114543e7cfb25859 100644 GIT binary patch delta 446 zcmbPXal&ST2Ga?tjan0VCJS*^PL|@#WMW{Lyqm{x^9Pw9DXLeX2C)DI zlz{lpe+Y2p1u0=*0Ew$?HWho#sJRB{ArJsjAPjTm1vK$DlO-kYGsW^w{v~0?xj`JH zg@IwhWJ^hNrn$V67fOgtzQE5ixkpk3nR^DvUBEl}lcXKz5~$TWlMnI>Pxg^gVY+~% z4Z__dWykpes_w(&pHdc_5)gX?m?m3En{hr6fN(1&S4x|6Muz)oUJ2NI H9!VYmC$nN{ delta 204 zcmX?MGs9wn2Gb0Qjan0VCePV2C7CzgXsg$WXYOw?%;=TB_^+wHRrq_ W1mW>cekp6tr62*}l`sIEA_o9~@ir0w diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 3ddee86b8e7ccbe0aaaca907a0382b222dde92f1..43c68ba59b31f398680c084e95aaf40cb8efff68 100644 GIT binary patch delta 24442 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 delta 15979 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
  • ?L*U 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 z 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 delta 33893 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 diff --git a/build/tensor.o b/build/tensor.o index 1e688037a3edea0101c07e79f9fbbfab6f0bc7d9..ce0b93c70d477a3fa9f7e9a7c897187f62279a20 100644 GIT binary patch delta 2624 zcmZ{mYe-Z<6vyx0bk*I=_g=RQE2K85z|^$1+>9P*WkwkmgxZ5BLM<)o(_Ka~$uP>-yMZ z{h~)73qQ&&%cCS$Y@~eYb!X&T@iRMR`7&)UDZ`g-8>BG5|Ikxkww^U3^2t{omtg2x zv^CQ3M#B~oZ+E9%(^55?=F69wY4a><(UJ`4GmT}$XC(Ji;vj1tt)g_EtlcMZesay$)UEF z>RJtVi&A5l&f(|JU)iqEC008@b%5GUU99#gHJ6n{P)BK;)iIbm3)Ekf$7-TVgos-K zY7PybHQXyf%>eZXrL-AkCqbPFY6tKX;1S?x|AtyP){s)o^D$50D?K`E*uK+ze*cJC zIt$n-H>+hb-D)%Zvz01#l*Ete=cr|tdH&5{p9c0Fz%e78z$?MNTk>2@1jZx{zy#d( zC>?7vY&vzFGu&~i*2P>*QVNZqGwO0c-3}qWz%gPa@C>kT0iFyzNSAmG4?xAVy^X3v zO0^c*PqBXgFPMw#k6FQCxLK3oRNU%qf#TNGE&@O3KTmT1lmKLLNpb5!?<#ICv{hZG55UhX%|CfK&q2VIegN)(z$3sjfM*r+fSWi8tXB{4iIev8 zg;@>)mheH~6BF3}wBptsUsT-Ov6=NS_`x!~!JPL$wa)KM6X4Y}0lKFN@D4bhXzNN5 zHF_2L|NE~JP=Yu*tn+)ovCeydV`>I~k9f>a9ZmgZncVsbV{)gL^b13YeJX-*rBP`x?Q$T~(IKt?ZtW$sAh1GD zU&EhFE@}*T%c|x;C?0#x-w{Ym4FwY3aY#<(j1ZeWv@iFW*43gYVtyP-n`@C#5Ei^6}9q zUF{65+%T=8Qa5tCjgQ}dr9GgX1=D&CY6#Rf)X&wgN^Rvz1k_a;FPNjhAa@g}K6Mvy z;%4AU;D>;B0Y41^)ccLoL&vln*a0hfM2q6?pvGYTA7nUY z_fJs6pl;v89d6=w1|Qyg+Q2csmu7F8)+wcWb$VH+N$2WW$i+G@)^jJ;$-OIbM<>_G zJ(dzxYMOVV*A*ue7xhQ^@G7|s9Q&jM96RKRBea&4o2)S!sHTIp>(Wio?W!GG-Y319pWapN UK$rAvGVa;IfFr&0G*@o=2imQL*#H0l diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index b9d5e9baaf7339d2cafbc1895c1cd7bb4b48def3..21215c7e87621d2a76cfe2e8eded9d80ed1496a3 100644 GIT binary patch delta 524 zcmYk3!A}!G6vp?Ph0Ri>X=qt(wUJg^*g`Ed81aBq!5$1DmIerwNW=k^CQzr1iOH&< zBwia|;sGwktA=RCi+4>tka#yzVE%?n@ln<*1pxlbKTt`gV*-M z@wJs(AHqjK>7^LM6kQS{xJGsHJ}1ZJQo3$CG$4wQ&%@X5DO~*$Uu5 zE06Y4N$k?6)PEzV;ysK<+M+SaXoN4~^u3zax6>=YJbgY}IAbA%n0XSma5xi)h#q0V zg2QRU(&2M=fsb^U&FH;M1^B8Dvr7U$^mTU^=+HlN3qXRl@-bZ*IuGPo7HGCBPGf^_ z%;xyg@`i^UYm kv{)==ChQo;fbH1PAbRbDKq#tudBn9;*dO1fcg35(0e_B&M*si- delta 356 zcmX?~-JZr5%FD~e00bTVR%wcn8~HvmG8#-`vS4(WY{_KE=r}o>X@gX%dWvm|T?<1q zW0XdUeTrBMLzHj|Q!s<3(`HxZFEWfSldTliNfy*FWHF>LW;0D-EDEb(M6f3_Dwa&H zR+N^u%R2^E!<@}Lfw4FbtOm?3Dx17fQI>Ja3 zPL?z|!*h$HpeVl}wWy@BsBZFHQ*rJhQD89f197p_WLZ-qMOzLLAk^Rx;}8ZyX(mQ4 TVXzWSwjw^Ds-pVIC8p5;u%2LG diff --git a/norch/autograd/__pycache__/functions.cpython-38.pyc b/norch/autograd/__pycache__/functions.cpython-38.pyc index 503e2427c9441aa1763b4e554f73cbbf18f265a8..73c0c12bdc44075afd84c55fb170e07c3a81bc33 100644 GIT binary patch delta 399 zcmcbi`AnZLl$V!_0SFo@Y|~75C-TWKUYMx8S;L(nMJh$Qg&{?{nJJ1F$dgHt1@dHp zJiZjhU)%13r}7wWXr-GoS8Q{j@xFkIIpBYIZ(cs38ad#N(3bF zkWp^(3vOOB37}97Ll#2{qa;HuQw?Jc(*nkY3?dBaKy!=Kfs&d`MXW&T7ISib@k-_* zb|AZmZ}L2D2{C>kvkHidS%3rsBNx=K%i43EP=vxFe$K8Kq8v_ hlOsf&*g)data[i]; } } + +void sin_tensor_cpu(Tensor* tensor, float* result_data) { + for (int i = 0; i < tensor->size; i++) { + result_data[i] = sinf(tensor->data[i]); + } +} + +void cos_tensor_cpu(Tensor* tensor, float* result_data) { + for (int i = 0; i < tensor->size; i++) { + result_data[i] = cosf(tensor->data[i]); + } +} diff --git a/norch/csrc/cpu.h b/norch/csrc/cpu.h index 6e0e2a3..9e5dc62 100644 --- a/norch/csrc/cpu.h +++ b/norch/csrc/cpu.h @@ -24,5 +24,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 sin_tensor_cpu(Tensor* tensor, float* result_data); +void cos_tensor_cpu(Tensor* tensor, float* result_data); #endif /* CPU_H */ diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 73efdd2..beae140 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -482,4 +482,50 @@ __host__ void assign_tensor_cuda(Tensor* tensor, float* result_data) { cudaDeviceSynchronize(); } +__global__ void sin_tensor_cuda_kernel(float* data, float* result_data, int size) { + + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < size) { + result_data[i] = sinf(data[i]); + } +} + +__host__ void sin_tensor_cuda(Tensor* tensor, float* result_data) { + + int number_of_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + sin_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 cos_tensor_cuda_kernel(float* data, float* result_data, int size) { + + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < size) { + result_data[i] = cosf(data[i]); + } +} + +__host__ void cos_tensor_cuda(Tensor* tensor, float* result_data) { + + int number_of_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + cos_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 d21beef..c92cfb1 100644 --- a/norch/csrc/cuda.h +++ b/norch/csrc/cuda.h @@ -52,6 +52,11 @@ __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 sin_tensor_cuda_kernel(float* data, float* result_data, int size); + __host__ void sin_tensor_cuda(Tensor* tensor, float* result_data); + + __global__ void cos_tensor_cuda_kernel(float* data, float* result_data, int size); + __host__ void cos_tensor_cuda(Tensor* tensor, float* result_data); diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 1c46245..837e720 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -105,6 +105,7 @@ extern "C" { } shape[i] = tensor1->shape[i]; } + if (strcmp(tensor1->device, "cuda") == 0) { float* result_data; @@ -854,6 +855,80 @@ extern "C" { } } + Tensor* sin_tensor(Tensor* tensor) { + 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 = tensor->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++) { + shape[i] = tensor->shape[i]; + } + + if (strcmp(tensor->device, "cuda") == 0) { + + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + sin_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, device); + } + else { + float* result_data = (float*)malloc(tensor->size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + sin_tensor_cpu(tensor, result_data); + return create_tensor(result_data, shape, ndim, device); + } + } + + Tensor* cos_tensor(Tensor* tensor) { + 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 = tensor->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++) { + shape[i] = tensor->shape[i]; + } + + if (strcmp(tensor->device, "cuda") == 0) { + + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + cos_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, device); + } + else { + float* result_data = (float*)malloc(tensor->size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + cos_tensor_cpu(tensor, result_data); + return create_tensor(result_data, shape, ndim, device); + } + } + Tensor* transpose_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 90b4d0d..d45901f 100644 --- a/norch/csrc/tensor.h +++ b/norch/csrc/tensor.h @@ -31,6 +31,8 @@ extern "C" { void to_device(Tensor* tensor, char* device); Tensor* ones_like_tensor(Tensor* tensor); Tensor* zeros_like_tensor(Tensor* tensor); + Tensor* sin_tensor(Tensor* tensor); + Tensor* cos_tensor(Tensor* tensor); Tensor* transpose_tensor(Tensor* tensor); Tensor* transpose_axes_tensor(Tensor* tensor, int axis1, int axis2); void make_contiguous(Tensor* tensor); diff --git a/norch/tensor.py b/norch/tensor.py index bd5bf18..3d309f9 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -402,6 +402,7 @@ class Tensor: result_data.shape = [other.shape[0], self.shape[1], other.shape[2]] result_data.ndim = 3 result_data.device = self.device + result_data.numel = 1 for s in result_data.shape: result_data.numel *= s else: @@ -422,6 +423,7 @@ class Tensor: result_data.shape = [self.shape[0], other.shape[1]] result_data.ndim = 2 result_data.device = self.device + result_data.numel = 1 for s in result_data.shape: result_data.numel *= s @@ -571,6 +573,46 @@ class Tensor: return result_data + def sin(self): + Tensor._C.sin_tensor.argtypes = [ctypes.POINTER(CTensor)] + Tensor._C.sin_tensor.restype = ctypes.POINTER(CTensor) + + result_tensor_ptr = Tensor._C.sin_tensor(self.tensor) + + result_data = Tensor() + result_data.tensor = result_tensor_ptr + result_data.shape = self.shape.copy() + result_data.ndim = self.ndim + result_data.device = self.device + result_data.numel = self.numel + + result_data.requires_grad = self.requires_grad + if result_data.requires_grad: + result_data.grad_fn = SinBackward(self) + + return result_data + + def cos(self): + Tensor._C.cos_tensor.argtypes = [ctypes.POINTER(CTensor)] + Tensor._C.cos_tensor.restype = ctypes.POINTER(CTensor) + + result_tensor_ptr = Tensor._C.cos_tensor(self.tensor) + + result_data = Tensor() + result_data.tensor = result_tensor_ptr + result_data.shape = self.shape.copy() + result_data.ndim = self.ndim + result_data.device = self.device + result_data.numel = self.numel + + result_data.requires_grad = self.requires_grad + if result_data.requires_grad: + result_data.grad_fn = CosBackward(self) + + return result_data + + + def transpose(self, axis1, axis2): if axis1 < 0: axis1 = self.ndim + axis1 @@ -596,7 +638,6 @@ class Tensor: result_data.grad_fn = TransposeBackward(self, axis1, axis2) return result_data - @property def T(self): @@ -611,7 +652,7 @@ class Tensor: result_data.ndim = self.ndim result_data.device = self.device result_data.numel = self.numel - + result_data.requires_grad = self.requires_grad if result_data.requires_grad: result_data.grad_fn = TBackward(self) diff --git a/tests/__init__.py b/tests/__init__.py index fef67f5..4750076 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,3 @@ -from .test_operations import * \ No newline at end of file +from .test_operations import * +from .test_autograd import * +from .test_nn import * \ No newline at end of file diff --git a/tests/test_autograd.py b/tests/test_autograd.py index 2ac0d92..d70cddd 100644 --- a/tests/test_autograd.py +++ b/tests/test_autograd.py @@ -128,7 +128,6 @@ class TestTensorAutograd(unittest.TestCase): self.assertTrue(utils.compare_torch(norch_tensor_grad_power_st, torch_tensor_grad_power_st)) - def test_power_tensor_scalar(self): """ Test autograd from tensor raised to scalar: tensor ** scalar @@ -207,6 +206,39 @@ class TestTensorAutograd(unittest.TestCase): self.assertTrue(utils.compare_torch(norch_tensor1_grad_elemwise_mul, torch_tensor1_grad_elemwise_mul)) self.assertTrue(utils.compare_torch(norch_tensor2_grad_elemwise_mul, torch_tensor2_grad_elemwise_mul)) + def test_sin_tensor(self): + """ + Test autograd from sin operation: sin(tensor) + """ + norch_sin_tensor = norch.Tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + norch_result_sin_tensor = (norch_sin_tensor.sin()).sum() + norch_result_sin_tensor.backward() + torch_result_sin_tensor_grad = utils.to_torch(norch_sin_tensor.grad) + + torch_sin_tensor = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).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 + + self.assertTrue(utils.compare_torch(torch_result_sin_tensor_grad, torch_expected_sin_tensor_grad)) + + def test_cos_tensor(self): + """ + Test autograd from cosine operation: cos(tensor) + """ + norch_cos_tensor = norch.Tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).to(self.device) + norch_result_cos_tensor = (norch_cos_tensor.sin()).sum() + norch_result_cos_tensor.backward() + torch_result_cos_tensor_grad = utils.to_torch(norch_cos_tensor.grad) + + torch_cos_tensor = torch.tensor([[[2, 3.21], [4, 2.1]], [[6, 7], [8, 9]]], requires_grad=True).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 + + self.assertTrue(utils.compare_torch(torch_result_cos_tensor_grad, torch_expected_cos_tensor_grad)) + + def test_reshape(self): """ Test autograd from reshaping a tensor: tensor.reshape(shape) diff --git a/tests/test_nn.py b/tests/test_nn.py index 483eac3..1bf12d3 100644 --- a/tests/test_nn.py +++ b/tests/test_nn.py @@ -4,7 +4,7 @@ from norch import utils import torch import os -class TestNNModule(unittest.TestCase): +class TestNNModuleLoss(unittest.TestCase): def setUp(self): self.device = os.environ.get('device') @@ -40,9 +40,16 @@ class TestNNModule(unittest.TestCase): labels_torch = torch.tensor([4, 3, 2.1, 1]) loss_torch_expected = loss_fn_torch(predictions_torch, labels_torch) - print(loss_torch_result, loss_torch_expected) self.assertTrue(utils.compare_torch(loss_torch_result, loss_torch_expected)) + +class TestNNModuleActivationFn(unittest.TestCase): + + def setUp(self): + self.device = os.environ.get('device') + if self.device is None or self.device != 'cuda': + self.device = 'cpu' + def test_sigmoid_activation(self): """ Test Sigmoid activation function @@ -78,7 +85,4 @@ class TestNNModule(unittest.TestCase): x = torch.tensor([0, 0, 0]) sigmoid_torch_expected = sigmoid_fn_torch.forward(x) - self.assertTrue(utils.compare_torch(sigmoid_torch_result, sigmoid_torch_expected)) - - - \ No newline at end of file + self.assertTrue(utils.compare_torch(sigmoid_torch_result, sigmoid_torch_expected)) \ No newline at end of file diff --git a/tests/test_operations.py b/tests/test_operations.py index 6ded830..ed72ec6 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -267,6 +267,58 @@ class TestTensorOperations(unittest.TestCase): self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + def test_tensor_sin(self): + """ + Test sine function on tensor + """ + norch_tensor = norch.Tensor([[[0, 30], [45, 60]], [[90, 120], [135, 180]]]).to(self.device) + norch_result = norch_tensor.sin() + torch_result = utils.to_torch(norch_result) + + torch_tensor = torch.tensor([[[0, 30], [45, 60]], [[90, 120], [135, 180]]]).to(self.device) + torch_expected = torch.sin(torch_tensor) + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + + def test_tensor_cos(self): + """ + Test cosine function on tensor + """ + norch_tensor = norch.Tensor([[[0, 30], [45, 60]], [[90, 120], [135, 180]]]).to(self.device) + norch_result = norch_tensor.cos() + torch_result = utils.to_torch(norch_result) + + torch_tensor = torch.tensor([[[0, 30], [45, 60]], [[90, 120], [135, 180]]]).to(self.device) + torch_expected = torch.cos(torch_tensor) + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + + + def test_zeros_like(self): + """ + Test creating a tensor of zeros with the same shape as another tensor. + """ + norch_tensor = norch.Tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + norch_zeros = norch_tensor.zeros_like() + torch_zeros_result = utils.to_torch(norch_zeros) + + torch_tensor_expected = torch.tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + torch_zeros_expected = torch.zeros_like(torch_tensor_expected) + + self.assertTrue(utils.compare_torch(torch_zeros_result, torch_zeros_expected)) + + def test_ones_like(self): + """ + Test creating a tensor of ones with the same shape as another tensor. + """ + norch_tensor = norch.Tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + norch_ones = norch_tensor.ones_like() + torch_ones_result = utils.to_torch(norch_ones) + + torch_tensor_expected = torch.tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + torch_ones_expected = torch.ones_like(torch_tensor_expected) + + self.assertTrue(utils.compare_torch(torch_ones_result, torch_ones_expected)) if __name__ == '__main__':