From a92b99177684b18b9a848ca351d4ed0ff781c827 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Sat, 4 May 2024 13:37:18 -0300 Subject: [PATCH] Fix transpose axis and make contigous --- build/cpu.o | Bin 5864 -> 5952 bytes build/libtensor.so | Bin 90336 -> 90576 bytes build/tensor.o | Bin 27496 -> 30472 bytes norch/__pycache__/tensor.cpython-38.pyc | Bin 9287 -> 9716 bytes .../__pycache__/functions.cpython-38.pyc | Bin 3473 -> 3501 bytes norch/autograd/functions.py | 2 +- norch/csrc/cpu.cpp | 43 +++---- norch/csrc/cpu.h | 5 +- norch/csrc/tensor.cpp | 117 +++++++++++++++++- norch/csrc/tensor.h | 3 + norch/tensor.py | 22 ++++ test.py | 60 ++++++++- 12 files changed, 217 insertions(+), 35 deletions(-) diff --git a/build/cpu.o b/build/cpu.o index 9f7b57930e478ea0ee1a31a6f42d792b6e0c7593..7a91d37602354ea58213790f208f86a99f5b21a2 100644 GIT binary patch delta 852 zcmZus&ubGw7@b+P$u6n8n=}DIikE^OENu!dG>0VWz<}V*iUmmv78RitQ%|yl5EYlD zP#A??1pNd2MLZO}Br2p9gdPKeEMj15a|mP)p#CIEP z_V)Btl)aC{$EcmtY{YIW^Q8})*FJUC$-~RkYEjE{sddkxHgSc-BE7K59kEEiK{^PI zO*$FUGnX2~6Rnpaee_C|t1Bvv79ynlZ%7*s%f zbiV*M_9`+}T~m%rR||ZM9Mc|2=f}sSg;*qt&)>tkUZ{1ksgKR-hSGV;UoDRHv9!7yD5&uFj|KKf| z{fd9bdG;k?$ZvFEc!tRn1}?MwL>6ip>H}7X`k3Kl7QbV8sN1ZZ%qmSqOdyHvCeO;w gaKTL`rwrU=`BYY3QibFavr>ja6QWy3Y&S9a8^D_fga7~l delta 823 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 literal 27496 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 diff --git a/norch/autograd/__pycache__/functions.cpython-38.pyc b/norch/autograd/__pycache__/functions.cpython-38.pyc index 033c83cd1c60857fd83e6998a3a3a94772fda7bd..d4ada96281c09dfbe6efc6f96498b279b4440368 100644 GIT binary patch delta 245 zcmbOzy;hnxl$V!_0SH*UOw+tK@@{1hV+Hb@fw));NYpT7F~l&{GSxEIFxD_HU`%05 zVOq!}z)-^kW7jYWFr+gDGiWmVz5EXZFaH4vO{O9ipzd3oB}IvO#Rd7rshj_>OEEIa zO@7NNK3R{m5Xf4<87n9YRHO#73#6KZk%MLO25zU#0bKr!!ty{7JtQgSBKgS;Ob(Mj xal0}qfQ|9ziC|Qmyn?4#SRJU&3`MQ_WIbL5ZjkXsAcKn3C;M}VPcGn91OVD!IF$eZ delta 217 zcmZ20JyDuBl$V!_0SMRxP11BX@@{3fVg~Y@fw))>NYpT7F~l&{GSxEIFxD_nUPC;au2T}02ogthX4Qo diff --git a/norch/autograd/functions.py b/norch/autograd/functions.py index bd52020..7ba219f 100644 --- a/norch/autograd/functions.py +++ b/norch/autograd/functions.py @@ -33,7 +33,7 @@ class MatmulBackward: def backward(self, gradient): x, y = self.input - return [gradient @ y.T, x.T @ gradient] + return [gradient @ y.transpose(-1,-2), x.transpose(-1,-2) @ gradient] class PowBackward: def __init__(self, x, power): diff --git a/norch/csrc/cpu.cpp b/norch/csrc/cpu.cpp index f0ad525..c45a8e9 100644 --- a/norch/csrc/cpu.cpp +++ b/norch/csrc/cpu.cpp @@ -116,7 +116,14 @@ void zeros_like_tensor_cpu(Tensor* tensor, float* result_data) { } } -/*void transpose_tensor_cpu(Tensor* tensor, float* result_data) { +void transpose_1D_tensor_cpu(Tensor* tensor, float* result_data) { + + for (int i = 0; i < tensor->shape[0]; i++) { + result_data[i] = tensor->data[i]; + } +} + +void transpose_2D_tensor_cpu(Tensor* tensor, float* result_data) { int rows = tensor->shape[0]; int cols = tensor->shape[1]; @@ -125,33 +132,17 @@ void zeros_like_tensor_cpu(Tensor* tensor, float* result_data) { result_data[j * rows + i] = tensor->data[i * cols + j]; } } -}*/ +} +void transpose_3D_tensor_cpu(Tensor* tensor, float* result_data) { + int depth = tensor->shape[0]; + int rows = tensor->shape[1]; + int cols = tensor->shape[2]; -void transpose_tensor_cpu(Tensor* tensor, float* result_data) { - int* shape = tensor->shape; - int ndim = tensor->ndim; - int* strides = (int*)malloc(ndim * sizeof(int)); - int* indices = (int*)calloc(ndim, sizeof(int)); - - strides[ndim - 1] = 1; - for (int i = ndim - 2; i >= 0; i--) { - strides[i] = strides[i + 1] * shape[i + 1]; - } - - int idx_result; - for (int idx_source = 0; idx_source < tensor->size; idx_source++) { - idx_result = 0; - for (int dim = 0; dim < ndim; dim++) { - idx_result += indices[dim] * strides[dim]; - } - result_data[idx_result] = tensor->data[idx_source]; - - indices[ndim - 1]++; - for (int dim = ndim - 1; dim > 0; dim--) { - if (indices[dim] == shape[dim]) { - indices[dim] = 0; - indices[dim - 1]++; + for (int i = 0; i < depth; 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]; } } } diff --git a/norch/csrc/cpu.h b/norch/csrc/cpu.h index ae3eae5..a3c5879 100644 --- a/norch/csrc/cpu.h +++ b/norch/csrc/cpu.h @@ -14,7 +14,10 @@ void pow_tensor_cpu(Tensor* tensor, float power, float* result_data); 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 transpose_1D_tensor_cpu(Tensor* tensor, float* result_data); +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); #endif /* CPU_H */ diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index f85759e..03cc657 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -60,6 +60,15 @@ extern "C" { } printf("]\n"); + printf("Strides: ["); + for (int i = 0; i < ndim; i++) { + printf("%d", tensor->strides[i]); + if (i < ndim - 1) { + printf(", "); + } + } + printf("]\n"); + /*printf("Data:\n["); for (int i = 0; i < stride; i++) { printf("%.2f", tensor->data[i]); @@ -715,8 +724,112 @@ extern "C" { fprintf(stderr, "Memory allocation failed\n"); exit(1); } - transpose_tensor_cpu(tensor, result_data); + switch (ndim) { + case 1: + transpose_1D_tensor_cpu(tensor, result_data); + break; + case 2: + transpose_2D_tensor_cpu(tensor, result_data); + break; + case 3: + transpose_3D_tensor_cpu(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); } } -} + + Tensor* transpose_axes_tensor(Tensor* tensor, int axis1, int axis2) { + 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]; + } + + shape[axis1] = tensor->shape[axis2]; + shape[axis2] = tensor->shape[axis1]; + + int size = tensor->size; + + if (strcmp(tensor->device, "cuda") == 0) { + + float* result_data; + cudaMalloc((void **)&result_data, size * sizeof(float)); + //transpose_axes_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); + } + //transpose_axes_cpu(tensor, result_data, axis1, axis2, shape); + assign_tensor_cpu(tensor, result_data); + + 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; + } + } + + 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; + } + + // Calculate new strides assuming C-contiguous order + int stride = 1; + for (int i = tensor->ndim - 1; i >= 0; i--) { + new_strides[i] = stride; + 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]; + } + + // Free old data and update tensor properties + free(tensor->data); + free(tensor->strides); + tensor->data = new_data; + tensor->strides = new_strides; + } + } diff --git a/norch/csrc/tensor.h b/norch/csrc/tensor.h index aa8d3e9..dab0b23 100644 --- a/norch/csrc/tensor.h +++ b/norch/csrc/tensor.h @@ -26,6 +26,9 @@ extern "C" { void to_device(Tensor* tensor, char* device); Tensor* ones_like_tensor(Tensor* tensor); Tensor* zeros_like_tensor(Tensor* tensor); + Tensor* transpose_tensor(Tensor* tensor); + Tensor* transpose_axes_tensor(Tensor* tensor, int axis1, int axis2); + void make_contiguous(Tensor* tensor); } #endif /* TENSOR_H */ diff --git a/norch/tensor.py b/norch/tensor.py index d22aa91..2b637c0 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -383,6 +383,28 @@ class Tensor: return result_data + def transpose(self, axis1, axis2): + if axis1 < 0: + axis1 = self.ndim + axis1 + if axis2 < 0: + axis2 = self.ndim + axis2 + + Tensor._C.transpose_axes_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.c_int, ctypes.c_int] + Tensor._C.transpose_axes_tensor.restype = ctypes.POINTER(CTensor) + + result_tensor_ptr = Tensor._C.transpose_axes_tensor(self.tensor, axis1, axis2) + + result_data = Tensor() + result_data.tensor = result_tensor_ptr + result_data.shape = self.shape.copy() + result_data.shape[axis1] = self.shape[axis2] + result_data.shape[axis2] = self.shape[axis1] + result_data.ndim = self.ndim + result_data.device = self.device + + return result_data + + @property def T(self): Tensor._C.transpose_tensor.argtypes = [ctypes.POINTER(CTensor)] diff --git a/test.py b/test.py index e86e5c2..22a0621 100644 --- a/test.py +++ b/test.py @@ -28,22 +28,72 @@ if __name__ == "__main__": [[7.890, 8.901], [9.012, 1.234], [2.345, 3.456]] ], requires_grad=True) - b = norch.Tensor([ + b = norch.Tensor([[ [1.234, 2.123, 1.5], [5.678, 6.789, 1.293], [3.635, 4.456, 1.0202], [7.890, 8.901, 1.91], - ]) + ],[ + [1.234, 2.123, 1.5], + [5.678, 6.789, 1.293], + [3.635, 4.456, 1.0202], + [7.890, 8.901, 1.91], + ],[ + [1.234, 2.123, 1.5], + [5.678, 6.789, 1.293], + [3.635, 4.456, 1.0202], + [7.890, 8.901, 1.91], + ],[ + [1.234, 2.123, 1.5], + [5.678, 6.789, 1.293], + [3.635, 4.456, 1.0202], + [7.890, 8.901, 1.91], + ],[ + [1.234, 2.123, 1.5], + [5.678, 6.789, 1.293], + [3.635, 4.456, 1.0202], + [7.890, 8.901, 1.91], + ]]) + #print(a.T) + #print(a.T.shape) + #[5, 3, 2] [4, 3] [5, 4, 2] + #print(a.shape, b.shape) #b = norch.Tensor([ # [1.234, 2.123, 1.5]]) + #result = b @ a - #print(a.shape) - c = a.reshape([2,3,5]) - print(b @ c) + + #### testar transpose axes!!!! make it contiguous + + tensor1 = norch.Tensor([[[1, 2], [3, 4], [5, 6]], + [[7, 8], [9, 10], [11, 12]], + [[13, 14], [15, 16], [17, 18]], + [[19, 20], [21, 22], [23, 24]], + [[25, 26], [27, 28], [29, 30]]]) + + # Reshape tensor1 to 2x3x5 + reshaped_tensor = tensor1.transpose(1, 0) + + # Create a 5x4 tensor + tensor2 = norch.Tensor([[1, 2, 3], + [5, 6, 7], + [9, 10, 11], + [13, 14, 15], + [17, 18, 19]]) + + tensor2 = tensor2.transpose(1,0) + + + # Multiply reshaped_tensor by tensor2 + result = tensor2 @ reshaped_tensor + print(result) + + #print(a.shape, b.shape, result.shape) #c = result.sum() #c.backward() #print(a.grad) + #print(a.transpose(2,1)) #a = norch.Tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]])#.to("cuda") #b = Tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]])#.to("cuda")