-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Expand optional static-typing for Buffer to include dimensionality #6574
Conversation
src/runtime/HalideBuffer.h
Outdated
* | ||
* The class optionally allocates and owns memory for the image using | ||
* a shared pointer allocated with the provided allocator. If they are | ||
* null, malloc and free are used. Any device-side allocation is | ||
* considered as owned if and only if the host-side allocation is | ||
* owned. */ | ||
template<typename T = void, int D = 4> | ||
template<typename T = void, | ||
int Dims = -1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably ought to introduce a constant, probably declared in class, for the -1. The name is something like "DimsUnconstrained".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DynamicDims
is defined (line 188) but it isn't visible to the template parameters; AFAICT I'd need to declare it outside the class. Would that be preferable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I think this is ready to land. Reviewers, please do your thing. |
@@ -61,7 +61,7 @@ int main(int argc, char **argv) { | |||
auto in = real_buffer(); | |||
for (int j = 0; j < kSize; j++) { | |||
for (int i = 0; i < kSize; i++) { | |||
in(i, j) = signal_1d[i] + signal_1d[j]; | |||
in(i, j, 0) = signal_1d[i] + signal_1d[j]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment explaining why real_buffer() is not 2D (The fft requires is written generically to require 3D inputs, even when they are real).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/runtime/HalideBuffer.h
Outdated
@@ -521,7 +556,9 @@ class Buffer { | |||
} | |||
|
|||
/** Get the dimensionality of the buffer. */ | |||
// TODO: make constexpr, optimize for const case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not handle this now. I think it's enough to just have an if (has_static_dimensions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/runtime/HalideBuffer.h
Outdated
@@ -885,6 +932,7 @@ class Buffer { | |||
* take ownership of the data, and does not set the host_dirty flag. */ | |||
template<typename Array, size_t N> | |||
explicit Buffer(Array (&vals)[N]) { | |||
// TODO: this could probably be made constexpr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO either handle the TODO now or remove it. If the compiler can constant-fold it, it will. There shouldn't be any benefit in explicitly marking it as constexpr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (comment removed)
Updating the apps to use static dimensionality in their generator inputs is left for a future PR? If you don't intend to do it right away, perhaps open a tracking issue. |
A lot of that is done in #6575; it would be easy enough to pull out those changes (without the deprecation part) and merge them. |
Oh right, I forgot about that other PR. |
- Allow as<> to optionally convert dimensionality as well - The default ctor shouldn't always assume Dims == 0 - make_static_shape_storage() can be more constrained
Convert most of the apps to use static Buffer dimensions where it makes sense. (This uncovered a few glitches in #6574.)
Working on #6585 found a few oversights I missed, PTAL if you like |
* wip * Update metadata_tester_generator.cpp * Update Generator.h * Update Generator.h * DynamicDims -> BufferDimsUnconstrained * Update fft_aot_test.cpp * Update HalideBuffer.h * Update HalideBuffer.h * Fix as<>(), default ctor in HalideBuffer.h - Allow as<> to optionally convert dimensionality as well - The default ctor shouldn't always assume Dims == 0 - make_static_shape_storage() can be more constrained * Add extra template arg to Buffer<>::as<> also * Realization::operator Buffer() needs to know about the extra template parameter too * halide_image_io.h needs some attention * Convert apps/ to use static Buffer dims where useful Convert most of the apps to use static Buffer dimensions where it makes sense. (This uncovered a few glitches in #6574.)
Currently,
Halide::Runtime::Buffer<>
* allows you to provide a static ElementType, which allows you to enforce compile-time type checking to ensure incompatible Buffers aren't intermixed. You can also defeat this by using an ElementType ofvoid
, which defers all type checking to runtime.Unfortunately, there isn't a way to do the same for the dimensionality of a Buffer; all checking for matching dimensionality is done at runtime. This PR proposes to extend
Halide::Runtime::Buffer<>
* to allow for optional specification of dimensionality as well, with only a slight incompatibility with existing code.Currently,
H::R::B<>
is a template with two arguments:H::R::B<typename T = void, int D = 4>
T
, which is the element type; if omitted, defaults tovoid
.D
, which specifies the amount of storage to reserve for dimensionality (but not the actual dimensionality); if omitted, defaults to4
. Note that I've often seen this argument specified on the (mistaken) assumption that it is the dimensionality! In practice, almost no code ever needs to specify this (with apps/hannk being the only notable counterexample that comes to mind).This PR proposes to change H::R::B<> to a template with three arguments:
H::R::B<typename T = void, int Dims = -1, int InClassDimStorage = ...>
T
, which is the element type; if omitted, defaults tovoid
. This is unchanged from previous behavior.Dims
, which specifies the dimensionality of the Buffer:Dims
>= 0, the Buffer must always havedimensions() == Dims
; attempts to (e.g.) construct or access such a buffer with the 'wrong' number of arguments will fail at compile time, assignment between Buffers with different dimensionality will fail at compile time,slice()
andembed()
will return properly-typed results, etc.Dims
== -1, the Buffer can have any dimensionality, with compatibility being checked at runtime. (Basically, the same behavior as before.)InClassDimStorage
, which is the same as the oldD
argument. Its default value is determined like so:Dims
is >= 1, its default value isDims
, since we shouldn't ever see any more or less.Dims
is 0, we use a default value of 1 (just to be defensive against rogue code that assumes a valid pointer for dims in all cases)TL;DR:
Buffer<>
,Buffer<void>
, orBuffer<SomeType>
should work as-is, unchanged, with this change.Buffer<void, SomeInt>
orBuffer<void, SomeInt>
will need attention to work after this change, but most uses I've seen fail at compile time and are easy to spot.Note that the Generator infrastructure was expanded to add appropriate overloads for
Input<>
andOutput<>
to infer dimensionality from the Buffer specification (and metadata_tester_generator.cpp was modified to use this approach, for testing purposes); if this PR is approved, it is my intent to follow up with a PR that deprecates the ability to specify dimensionality in the old way.*all this also applies to Halide::Buffer<> as well, just omitting it above for simplicitly