Create and print a tensor
This commit is contained in:
parent
e05e85663d
commit
06b82066ae
8 changed files with 257 additions and 0 deletions
29
build/Makefile
Normal file
29
build/Makefile
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Compiler
|
||||
CXX := g++
|
||||
|
||||
# Compiler flags
|
||||
CXXFLAGS := -Wall -Werror -fpic
|
||||
|
||||
# Source files
|
||||
SRCS := ../src/tensor.cpp
|
||||
|
||||
# Object files
|
||||
OBJS := $(SRCS:.cpp=.o)
|
||||
|
||||
# Target shared object file
|
||||
TARGET := libtensor.so
|
||||
|
||||
# Default target
|
||||
all: $(TARGET)
|
||||
|
||||
# Rule to build the shared object file
|
||||
$(TARGET): $(OBJS)
|
||||
$(CXX) -shared -o $@ $^
|
||||
|
||||
# Rule to compile each source file into an object file
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $^ -o $@ # Use -o $@ to specify the output file
|
||||
|
||||
# Clean rule
|
||||
clean:
|
||||
$(RM) $(OBJS) $(TARGET)
|
||||
BIN
build/libtensor.so
Executable file
BIN
build/libtensor.so
Executable file
Binary file not shown.
BIN
python/__pycache__/tensor.cpython-39.pyc
Normal file
BIN
python/__pycache__/tensor.cpython-39.pyc
Normal file
Binary file not shown.
54
python/tensor.py
Normal file
54
python/tensor.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
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)
|
||||
]
|
||||
|
||||
class Tensor:
|
||||
def __init__(self, data, shape):
|
||||
self.lib = ctypes.CDLL("../build/libtensor.so") # Adjust the path to the shared library
|
||||
self.data = (ctypes.c_float * len(data))(*data)
|
||||
self.shape = shape
|
||||
self.ndim = len(shape)
|
||||
|
||||
self.lib.create_tensor.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_int), ctypes.c_int]
|
||||
self.lib.create_tensor.restype = ctypes.POINTER(CTensor)
|
||||
|
||||
self.tensor = self.lib.create_tensor(
|
||||
self.data,
|
||||
(ctypes.c_int * len(shape))(*shape),
|
||||
ctypes.c_int(len(shape))
|
||||
)
|
||||
|
||||
def __getitem__(self, indices):
|
||||
if len(indices) != self.ndim:
|
||||
raise ValueError("Number of indices must match the number of dimensions")
|
||||
|
||||
self.lib.get_item.argtypes = [ctypes.POINTER(CTensor), ctypes.POINTER(ctypes.c_int)]
|
||||
self.lib.get_item.restype = ctypes.c_float
|
||||
|
||||
indices = (ctypes.c_int * len(indices))(*indices)
|
||||
value = self.lib.get_item(self.tensor, indices)
|
||||
|
||||
return value
|
||||
|
||||
def __del__(self):
|
||||
self.lib.free_tensor(self.tensor)
|
||||
|
||||
def shape(self):
|
||||
return f"Tensor(shape={self.shape})"
|
||||
|
||||
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__()
|
||||
90
python/tests.ipynb
Normal file
90
python/tests.ipynb
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"kkkk <tensor.c_int_Array_2 object at 0x7f990806fcc0> @@ c_int(2)\n",
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "ValueError",
|
||||
"evalue": "Number of indices must match the number of dimensions",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
|
||||
"Cell \u001b[0;32mIn[1], line 6\u001b[0m\n\u001b[1;32m 4\u001b[0m shape \u001b[38;5;241m=\u001b[39m [\u001b[38;5;241m3\u001b[39m, \u001b[38;5;241m3\u001b[39m]\n\u001b[1;32m 5\u001b[0m tensor \u001b[38;5;241m=\u001b[39m Tensor(data, shape)\n\u001b[0;32m----> 6\u001b[0m \u001b[43mTensor\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__getitem__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mtensor\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n",
|
||||
"File \u001b[0;32m~/Documentos/recreate_pytorch/foo/python/tensor.py:15\u001b[0m, in \u001b[0;36mTensor.__getitem__\u001b[0;34m(self, indices)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__getitem__\u001b[39m(\u001b[38;5;28mself\u001b[39m, indices):\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(indices) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mndim:\n\u001b[0;32m---> 15\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNumber of indices must match the number of dimensions\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 16\u001b[0m indices \u001b[38;5;241m=\u001b[39m (ctypes\u001b[38;5;241m.\u001b[39mc_int \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mlen\u001b[39m(indices))(\u001b[38;5;241m*\u001b[39mindices)\n\u001b[1;32m 17\u001b[0m value \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlib\u001b[38;5;241m.\u001b[39mget_item(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtensor, indices) \n",
|
||||
"\u001b[0;31mValueError\u001b[0m: Number of indices must match the number of dimensions"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from tensor import Tensor\n",
|
||||
"\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.shape\n",
|
||||
"Tensor.__getitem__(tensor, [0, 0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"-648269760\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(tensor[1, 1]) # Accessing an element"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
67
src/tensor.cpp
Normal file
67
src/tensor.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#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->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("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");
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
void free_tensor(Tensor *tensor) {
|
||||
free(tensor->data);
|
||||
free(tensor->shape);
|
||||
free(tensor->strides);
|
||||
free(tensor);
|
||||
}
|
||||
}
|
||||
17
src/tensor.h
Normal file
17
src/tensor.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef TENSOR_H
|
||||
#define TENSOR_H
|
||||
|
||||
typedef struct {
|
||||
float *data;
|
||||
int *strides;
|
||||
int *shape;
|
||||
int ndim;
|
||||
} Tensor;
|
||||
|
||||
extern "C" {
|
||||
Tensor *create_tensor(float *data, int *shape, int ndim);
|
||||
float get_item(Tensor *tensor, int *indices);
|
||||
void delete_tensor(Tensor* tensor);
|
||||
}
|
||||
|
||||
#endif /* TENSOR_H */
|
||||
BIN
src/tensor.o
Normal file
BIN
src/tensor.o
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue