Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Halide copy behaviour for zero strides #8498

Closed
steven-johnson opened this issue Dec 7, 2024 · 1 comment
Closed

Halide copy behaviour for zero strides #8498

steven-johnson opened this issue Dec 7, 2024 · 1 comment

Comments

@steven-johnson
Copy link
Contributor

When making a copy of a Halide buffer with a dimension with stride 0, the copy will always have a stride of 1 for that dimension, changing the overall buffer size.

Example:

  const int kWidth = 100;
  const int kHeight = 100;
  const int kChannels = 3;
  Halide::Runtime::Buffer<uint8_t> buffer(kWidth, kHeight);
  LOG(INFO) << "buffer initial: ";
  LogBufferDimensions(buffer);
  buffer.add_dimension_with_stride(0);
  buffer.raw_buffer()->dim[2].extent = kChannels;
  buffer.set_host_dirty();
  LOG(INFO) << "buffer after adding dimension: ";
  LogBufferDimensions(buffer);
  Halide::Runtime::Buffer<uint8_t> copy = buffer.copy();
  LOG(INFO) << "buffer copy: ";
  LogBufferDimensions(copy);

will produce output

buffer initial: 
dim 0: min=0, extent=100, stride=1
dim 1: min=0, extent=100, stride=100
buffer after adding dimension: 
dim 0: min=0, extent=100, stride=1
dim 1: min=0, extent=100, stride=100
dim 2: min=0, extent=3, stride=0
buffer copy: 
dim 0: min=0, extent=100, stride=3
dim 1: min=0, extent=100, stride=300
dim 2: min=0, extent=3, stride=1

Is that a bug in Halide's copy() method or is a stride of 0 actually forbidden? I guess this happens because the dimension will the smallest stride is always set to a stride of 1 in make_with_shape_of_helper()

@abadams
Copy link
Member

abadams commented Dec 7, 2024

After thinking through the implications, I think that's WAI and the comment needs updating. The comment says "The new image uses the same memory layout as the original, with holes compacted away.", but the behavior is actually "The new image has the same nesting order of dimensions (e.g. channels innermost), but resets the strides to the default (each stride is the product of the extents of the inner dimensions). Note that this means any strides of zero get broadcast into a non-zero stride."

This follows from the rule: when you use a buffer as a halide pipeline output, or the output of one of the methods in Halide::Runtime::Buffer, it is undefined behavior if two distinct coordinates map to the same memory address. You may use such buffers as inputs only.

This rule is necessary because our scheduling directives and Halide::Runtime::Buffer methods assume values can be written in any order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants