-2
import torch
import numpy as np

aray = np.arange(1, 11)
tensor = torch.from_numpy(aray)
print(f"aray: {aray}, \ntensor: {tensor}\n\n\n")

aray = 1 + aray
print(f"aray + 1: {aray}, \ntensor: {tensor}")

When I use aray += 1, the tensor variable changes too, but when I use aray = aray + 1 it doesn't. Why?

jared
  • 4,165
  • 1
  • 8
  • 31
  • did you use `aray + 1` or `1 + aray`? – Albin Paul Aug 30 '23 at 10:13
  • both give the same output – Igor czerbniak Aug 30 '23 at 10:14
  • In your code, when you use `aray += 1`, you're performing an in-place operation that modifies the existing NumPy array. On the other hand, when you use `aray = aray + 1`, you are creating a new NumPy array by adding 1 element-wise to the existing aray. This new array is assigned back to the aray variable. However, this operation doesn't modify the original NumPy array. – Linux Aug 30 '23 at 10:14
  • so is this tutorial wrong at 3:39:15? https://www.youtube.com/watch?v=V_xro1bcAuA&t=11312s – Igor czerbniak Aug 30 '23 at 10:19
  • Indeed, the tutorial is wrong at that point, in saying "If you use `from_numpy()`, we get a new tensor in memory" (3:39:30). Here is the correctly timestamped link for 3:39:15, by the way: https://www.youtube.com/watch?v=V_xro1bcAuA&t=13155s – simon Aug 30 '23 at 14:00

2 Answers2

1

I see the source of the confusion now. In your code, when you use aray += 1, it indeed modifies both aray and tensor because tensor is created using torch.from_numpy(aray), which means it shares its underlying data with the NumPy array aray. This behavior is a result of how NumPy and PyTorch handle memory management and array operations.

Here's what happens:

aray is a NumPy array containing integers from 1 to 10. tensor is created from aray using torch.from_numpy(aray). This means tensor shares the same underlying data with aray. When you do aray += 1, it modifies the original NumPy array aray in place. Since tensor shares the same data, it also reflects the changes.

However, when you do aray = aray + 1, you are creating a new NumPy array that results from adding 1 to each element of the original aray. This new array is then assigned to the variable aray. This doesn't modify the original array in place, and tensor still references the old data.

If you want tensor to reflect the changes in this case, you would need to recreate it from the updated aray:

import torch
import numpy as np

aray = np.arange(1, 11)
tensor = torch.from_numpy(aray)
print(f"aray: {aray}, \ntensor: {tensor}\n\n\n")

aray = aray + 1  # Create a new array with updated values
tensor = torch.from_numpy(aray)  # Update 'tensor' to reflect the changes
print(f"aray + 1: {aray}, \ntensor: {tensor}")

Now, tensor will correctly reflect the changes made to aray using aray = aray + 1.

jared
  • 4,165
  • 1
  • 8
  • 31
  • so is this tutorial wrong at 3:39:15? https://www.youtube.com/watch?v=V_xro1bcAuA&t=11312s – Igor czerbniak Aug 30 '23 at 10:21
  • Correct link for 3:39:15 is https://www.youtube.com/watch?v=V_xro1bcAuA&t=13155s. Wrong statement is a few seconds later (3:39:30) – simon Aug 30 '23 at 14:02
1

As Sparsh Choudhary explained in their answer, because you used torch.from_numpy, they end up referencing the same memory location. When using += (i.e. __iadd__), the memory address stays the same (the operation is performed in-place when possible, see this question). But when you perform aray = aray + 1, you're creating a new array, so the result no longer references the original memory address (since it's a completely new array). But tensor is unchanged and will still point to the original memory address.

We can check this by getting the memory pointers for the numpy array and pytorch tensor (the methods for each are slightly different, see this answer).

import torch
import numpy as np

aray = np.arange(1, 11)
tensor = torch.from_numpy(aray)

print(f"aray: {aray}")
print(f"tensor: {tensor}")

print(f"aray pointer: {aray.ctypes.data}")
print(f"tensor pointer: {tensor.data_ptr()}")

print("Inplace Addition:")
aray += 1
print(f"aray: {aray}")
print(f"tensor: {tensor}")

print(f"aray pointer: {aray.ctypes.data}")
print(f"tensor pointer: {tensor.data_ptr()}")


print("Normal Addition")

aray = 1 + aray
print(f"aray: {aray}")
print(f"tensor: {tensor}")

print(f"aray pointer: {aray.ctypes.data}")
print(f"tensor pointer: {tensor.data_ptr()}")

Output:

aray: [ 1  2  3  4  5  6  7  8  9 10]
tensor: tensor([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
aray pointer: 62868976
tensor pointer: 62868976
Inplace Addition:
aray: [ 2  3  4  5  6  7  8  9 10 11]
tensor: tensor([ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
aray pointer: 62868976
tensor pointer: 62868976
Normal Addition
aray: [ 3  4  5  6  7  8  9 10 11 12]
tensor: tensor([ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
aray pointer: 62869120
tensor pointer: 62868976

As you can see, after they are created, they share the same memory address, and this persists through the += operation. But once you perform aray = aray + 1, aray now references a new location in memory.

jared
  • 4,165
  • 1
  • 8
  • 31