Tensor¶
Introduction¶
n2d2.Tensor
is a wrapper of the Tensor
object available in N2D2 (see Tensor).
The class n2d2.Tensor
contains a reference to the element which produce it and can be seen as the edge of the computation graph.
Tensor¶
Manipulating tensors¶
For setting and getting value we will be using the following tensor as an example :
tensor = n2d2.Tensor([2, 3])
0 0 0
0 0 0
You can set and get values using :
Coordinates¶
tensor[1,0] = 1 # Using coordinates
value = tensor[1,0]
If you print the tensor you will see :
0 0 0
1 0 0
Index¶
You can use an index to get or set elements of a tensor. The index correspond to the flatten representation of your tensor.
tensor[0] = 2
value = tensor[0]
If you print the tensor you will see :
2 0 0
0 0 0
Slice¶
Note
Slice are supported only for assignment !
tensor[1:3] = 3
If you print the tensor you will see :
0 3 3
0 0 0
Set values method¶
If you want to set multiple values easily, you can use the method n2d2.Tensor.set_values()
tensor.set_values([[1,2,3], [4,5,6]])
If you print the tensor you will see :
1 2 3
4 5 6
Numpy¶
To Numpy¶
You can create a numpy.array
using a n2d2.Tensor
with the class method : n2d2.Tensor.to_numpy()
tensor = n2d2.Tensor([2, 3])
np_array = tensor.to_numpy()
This will create the following tensor :
0 0 0
0 0 0
By default the numpy.array
doesn’t create a memory copy meaning that if you want to manipulate a n2d2.Tensor
you can use the numpy library.
np_array[0] = 1
print(tensor)
1 1 1
0 0 0
Note
If you do not want to create a memory copy, you should set the parameter copy=True
.
np_array = tensor.to_numpy(copy=True)
From Numpy¶
You can create a n2d2.Tensor
using a numpy.array
with the class method : n2d2.Tensor.from_numpy()
np_array = numpy.array([[1,2,3], [4,5,6]])
tensor = n2d2.Tensor.from_numpy(np_array)
This will create the following tensor :
1 2 3
4 5 6
Note
You cannot create a n2d2.Tensor
from a numpy.array
without a memory copy because Tensor require a contiguous memory space which is not required for an array.
CUDA Tensor¶
You can store your tensor with CPU or GPU (using CUDA
). By default, n2d2 creates a CPU tensor.
If you want to create a CUDA
Tensor you can do so by setting the parameter cuda
to True in the constructor
tensor = n2d2.Tensor([2,3], cuda=True)
You can switch from CPU to GPU at anytime :
tensor.cpu() # Converting to a CPU tensor
tensor.cuda() # Converting to a CUDA tensor
When working on a CUDA
tensor you have to understand that they are stored in two different places.
The host and the device. The device is the GPU. The host correspond to your interface with the tensor that exists in the GPU. You cannot access the device directly, the GPU don’t have input/output functions.
This is why you have two methods to synchronized these two versions (n2d2.Tensor.htod()
and n2d2.Tensor.dtoh()
).
Synchronizing the device and the host can be an important overhead, it is recommended to compute everything on the device and to synchronize the host at the end.
Synchronization example¶
Let’s consider the following CUDA
Tensor :
t = n2d2.Tensor([2, 2], cuda=True)
0 0
0 0
We set the following values :
t.set_values([[1, 2], [3, 4]])
1 2
3 4
Then we will synchronized the device with the host. this mean that we send the values to the GPU.
t.htod()
1 2
3 4
As you can see, nothing change when printing the tensor. We have updated the GPU with the new values. Now let’s change the values stored in the tensor :
t.set_values([[2, 3], [4, 5]])
2 3
4 5
When printing the tensor we see the new values we just set. Now let’s synchronize the host with the device !
t.dtoh()
1 2
3 4
As you can see when printing the tensor, we now have the old values of the tensor.