Add tensors (still need to fix)
This commit is contained in:
parent
daff666ab4
commit
48f8c1d83d
10 changed files with 350 additions and 1 deletions
|
|
@ -5,7 +5,7 @@ CXX := g++
|
|||
CXXFLAGS := -Wall -Werror -fpic
|
||||
|
||||
# Source files
|
||||
SRCS := ../src/tensor.cpp
|
||||
SRCS := ../csrc/tensor.cpp
|
||||
|
||||
# Object files
|
||||
OBJS := $(SRCS:.cpp=.o)
|
||||
|
|
|
|||
Binary file not shown.
138
csrc/tensor.cpp
Normal file
138
csrc/tensor.cpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "tensor.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Tensor* create_tensor(float* data, int* shape, int ndim) {
|
||||
Tensor* tensor = (Tensor*)malloc(sizeof(Tensor));
|
||||
if (tensor == NULL) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
tensor->data = data;
|
||||
tensor->shape = shape;
|
||||
tensor->ndim = ndim;
|
||||
tensor->size = 1;
|
||||
|
||||
for (int i = 0; i < ndim; i++) {
|
||||
tensor->size *= shape[i];
|
||||
}
|
||||
|
||||
tensor->strides = (int*)malloc(ndim * sizeof(int));
|
||||
if (tensor->strides == NULL) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
int stride = 1;
|
||||
for (int i = ndim - 1; i >= 0; i--) {
|
||||
tensor->strides[i] = stride;
|
||||
stride *= shape[i];
|
||||
}
|
||||
|
||||
printf("Tensor created successfully\n");
|
||||
printf("Tensor information:\n");
|
||||
printf("Number of dimensions: %d\n", tensor->ndim);
|
||||
printf("Number size: %d\n", tensor->size);
|
||||
printf("Shape: [");
|
||||
for (int i = 0; i < ndim; i++) {
|
||||
printf("%d", tensor->shape[i]);
|
||||
if (i < ndim - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
printf("Data:\n[");
|
||||
for (int i = 0; i < stride; i++) {
|
||||
printf("%.2f", tensor->data[i]);
|
||||
if (i < stride - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]\n\n\n");
|
||||
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
float get_item(Tensor* tensor, int* indices) {
|
||||
int index = 0;
|
||||
for (int i = 0; i < tensor->ndim; i++) {
|
||||
index += indices[i] * tensor->strides[i];
|
||||
}
|
||||
return tensor->data[index];
|
||||
}
|
||||
|
||||
Tensor* add_tensor(Tensor* tensor1, Tensor* tensor2) {
|
||||
if (tensor1->ndim != tensor2->ndim) {
|
||||
fprintf(stderr, "Tensors must have the same number of dimensions %d and %d for addition\n", tensor1->ndim, tensor2->ndim);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int ndim = tensor1->ndim;
|
||||
int* shape = (int*)malloc(ndim * sizeof(int));
|
||||
if (shape == NULL) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Size: %d\n", tensor1->size);
|
||||
printf("Data: [");
|
||||
for (int i = 0; i < tensor1->size; i++) {
|
||||
printf("%.2f", tensor1->data[i]);
|
||||
if (i < tensor1->size - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
printf("Size: %d\n", tensor2->size);
|
||||
printf("Data: [");
|
||||
for (int i = 0; i < tensor2->size; i++) {
|
||||
printf("%.2f", tensor2->data[i]);
|
||||
if (i < tensor2->size - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
printf("Shapes : [");
|
||||
for (int i = 0; i < tensor1->ndim; i++) {
|
||||
printf("%d", tensor1->shape[i]);
|
||||
if (i < tensor1->ndim - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
printf("Shapes : [");
|
||||
for (int i = 0; i < tensor2->ndim; i++) {
|
||||
printf("%d", tensor2->shape[i]);
|
||||
if (i < tensor2->ndim - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
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 addition\n", tensor1->shape[i], tensor2->shape[i], i);
|
||||
exit(1);
|
||||
}
|
||||
shape[i] = tensor1->shape[i];
|
||||
}
|
||||
|
||||
float* result_data = (float*)malloc(tensor1->size * sizeof(float));
|
||||
if (result_data == NULL) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < tensor1->size; i++) {
|
||||
result_data[i] = tensor1->data[i] + tensor2->data[i];
|
||||
}
|
||||
|
||||
return create_tensor(result_data, shape, ndim);
|
||||
}
|
||||
}
|
||||
19
csrc/tensor.h
Normal file
19
csrc/tensor.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef TENSOR_H
|
||||
#define TENSOR_H
|
||||
|
||||
typedef struct {
|
||||
float *data;
|
||||
int* strides;
|
||||
int* shape;
|
||||
int ndim;
|
||||
int size;
|
||||
} Tensor;
|
||||
|
||||
extern "C" {
|
||||
Tensor* create_tensor(float* data, int* shape, int ndim);
|
||||
float get_item(Tensor* tensor, int* indices);
|
||||
Tensor* create_tensor(float* data, int* shape, int ndim);
|
||||
Tensor* add_tensor(Tensor* tensor1, Tensor* tensor2);
|
||||
}
|
||||
|
||||
#endif /* TENSOR_H */
|
||||
BIN
csrc/tensor.o
Normal file
BIN
csrc/tensor.o
Normal file
Binary file not shown.
BIN
norch/__pycache__/tensor.cpython-38.pyc
Normal file
BIN
norch/__pycache__/tensor.cpython-38.pyc
Normal file
Binary file not shown.
BIN
norch/__pycache__/tensor.cpython-39.pyc
Normal file
BIN
norch/__pycache__/tensor.cpython-39.pyc
Normal file
Binary file not shown.
89
norch/tensor.py
Normal file
89
norch/tensor.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import ctypes
|
||||
|
||||
class CTensor(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('data', ctypes.POINTER(ctypes.c_float)),
|
||||
('strides', ctypes.POINTER(ctypes.c_int)),
|
||||
('shape', ctypes.POINTER(ctypes.c_int)),
|
||||
('ndim', ctypes.c_int),
|
||||
('size', ctypes.c_int),
|
||||
]
|
||||
|
||||
class Tensor:
|
||||
_C = ctypes.CDLL("../build/libtensor.so")
|
||||
|
||||
def __init__(self, data):
|
||||
data, shape = self.flatten(data)
|
||||
# Adjust the path to the shared library
|
||||
self.data = (ctypes.c_float * len(data))(*data)
|
||||
self.shape = shape
|
||||
self.ndim = len(shape)
|
||||
|
||||
Tensor._C.create_tensor.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_int), ctypes.c_int]
|
||||
Tensor._C.create_tensor.restype = ctypes.POINTER(CTensor)
|
||||
|
||||
self.tensor = Tensor._C.create_tensor(
|
||||
self.data,
|
||||
(ctypes.c_int * len(shape))(*shape),
|
||||
ctypes.c_int(len(shape))
|
||||
)
|
||||
|
||||
def flatten(self, nested_list):
|
||||
flat_data = []
|
||||
shape = [len(nested_list), len(nested_list[0])]
|
||||
for sublist in nested_list:
|
||||
for item in sublist:
|
||||
flat_data.append(item)
|
||||
return flat_data, shape
|
||||
|
||||
def __getitem__(self, indices):
|
||||
if len(indices) != self.ndim:
|
||||
raise ValueError("Number of indices must match the number of dimensions")
|
||||
|
||||
Tensor._C.get_item.argtypes = [ctypes.POINTER(CTensor), ctypes.POINTER(ctypes.c_int)]
|
||||
Tensor._C.get_item.restype = ctypes.c_float
|
||||
|
||||
indices = (ctypes.c_int * len(indices))(*indices)
|
||||
value = Tensor._C.get_item(self.tensor, indices)
|
||||
|
||||
return value
|
||||
|
||||
def __str__(self):
|
||||
result = ""
|
||||
for i in range(self.shape[0]):
|
||||
for j in range(self.shape[1]):
|
||||
result += str(self[i, j]) + " "
|
||||
result += "\n"
|
||||
return result.strip()
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __add__(self, other):
|
||||
if self.shape != other.shape:
|
||||
raise ValueError("Tensors must have the same shape for addition")
|
||||
|
||||
Tensor._C.add_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.POINTER(CTensor)]
|
||||
Tensor._C.add_tensor.restype = ctypes.POINTER(CTensor)
|
||||
|
||||
result_tensor_ptr = Tensor._C.add_tensor(self.tensor, other.tensor)
|
||||
|
||||
result_data = [result_tensor_ptr.contents.data[i] for i in range(self.shape[0] * self.shape[1])]
|
||||
result_shape = [result_tensor_ptr.contents.shape[i] for i in range(result_tensor_ptr.contents.ndim)]
|
||||
|
||||
return Tensor(result_data, result_shape)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from tensor import Tensor
|
||||
import time
|
||||
|
||||
ini = time.time()
|
||||
a = Tensor([[1, 2, 3], [1, 2, 3]])
|
||||
b = Tensor([[1, 2, 3], [1, 2, 3]])
|
||||
|
||||
|
||||
c = a + b
|
||||
fim = time.time()
|
||||
|
||||
print(fim-ini)
|
||||
98
norch/tests.ipynb
Normal file
98
norch/tests.ipynb
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[0, 1, 2, 0, 2, 2] [2, 3, 3]\n",
|
||||
"Tensor shape: [2, 3, 3]\n",
|
||||
"Tensor created successfully\n",
|
||||
"Tensor information:\n",
|
||||
"Number of dimensions: 3\n",
|
||||
"Shape: [2, 3, 3]\n",
|
||||
"Data:\n",
|
||||
"[0.00, 1.00, 2.00, 0.00, 2.00, 2.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from tensor import Tensor\n",
|
||||
"\n",
|
||||
"data = [[0, 1, 2], [0, 2, 2], [0, 1, 2]]\n",
|
||||
"tensor = Tensor(data)\n",
|
||||
"print(\"Tensor shape:\", tensor.shape)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Tensor created successfully\n",
|
||||
"Tensor information:\n",
|
||||
"Number of dimensions: 2\n",
|
||||
"Shape: [3, 3]\n",
|
||||
"Data:\n",
|
||||
"[0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"0.10000000149011612 0.20000000298023224 0.30000001192092896 \n",
|
||||
"0.4000000059604645 0.5 0.6000000238418579 \n",
|
||||
"0.699999988079071 0.800000011920929 0.8999999761581421"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"\n",
|
||||
"data = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]\n",
|
||||
"shape = [3, 3]\n",
|
||||
"tensor = Tensor(data, shape)\n",
|
||||
"tensor\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.5"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
5
test.sh
Executable file
5
test.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
cd build
|
||||
make
|
||||
cd ..
|
||||
cd norch
|
||||
python3 tensor.py
|
||||
Loading…
Add table
Add a link
Reference in a new issue