Data format and stride
First of all, What is channel last format? Is it NHWC?
For the following code, how stride is calculated?
import torch
N, C, H, W = 10, 3, 32, 32
x = torch.empty(N, C, H, W)
print(x.stride()) # Ouputs: (3072, 1024, 32, 1)

Output is (3072, 1024, 32, 1)
When converted to channel last format, how stride is calculated here?
x = x.contiguous(memory_format=torch.channels_last)
print(x.shape) # Outputs: (10, 3, 32, 32) as dimensions order preserved
print(x.stride()) # Outputs: (3072, 1, 96, 3)

Output is torch.Size([10, 3, 32, 32])
(3072, 1, 96, 3)

TLDR: stride is the number of elements in the storage that need to be skipped over to obtain the next element along each dimension.

I believe you're referring to this tutorial.
Since every tensor references an underlying storage, you can have multiple tensors referencing the same storage with different strides and dimensions.
For e.g., I might have a 3x3 tensor:
[1 2 4
 0 4 5
 7 8 0]

but all that data is actually stored in a 1D contiguous storage, i.e. [1 2 4 0 4 5 7 8 0]. In order for the tensor to know how it should presented (i.e. 3x3), we need a stride property which is &quot;the number of elements in the storage that need to be skipped over to obtain the next element along each dimension&quot;. The stride for this would be (3,1), meaning I need to step over 3 elements in storage to get my next element in the first dimension and step over 1 element to get the next element in the second dimension. E.g.

starts with 1. To get the next value in the row dimension, add 3 (as indicated by stride). So the third element after 1 in storage is 0.
another e.g., let's start with the 2. To get the next value in the second dimension (col), add 1 in storage, which gives me 4.

That's the basics of how stride is calculated.
Back to your original question,

N, C, H, W = 10, 3, 32, 32

To get the stride, say of N, and let's say N is the n'th image, then I need to skip over (32 x 32 x 3 = 3072) elements in order to get to the start of the next image. Hence why stride() = (3072, 1024, 32, 1) on the first dimension. The same logic applies to the other strides.
From the tutorial linked above, channels last is simply a different way to store the underlying storage object in memory (see the pic in link). The stride changes due to how the contiguous memory is allocated, but the way we interpret and understand stride remains the same.
