Skip to content

Commit b352a68

Browse files
authored
ck-builder: tensor input/output reflection (#3536)
This adds some utilities to automatically generate UniqueInputs, UniqueOutputs, alloc_inputs, alloc_outputs, and validate, based on a Inputs::reflect() and Outputs::reflect().
1 parent 32408c8 commit b352a68

8 files changed

Lines changed: 299 additions & 102 deletions

File tree

experimental/builder/include/ck_tile/builder/testing/conv_fwd.hpp

Lines changed: 9 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "ck_tile/builder/factory/helpers/ck/conv_tensor_layout.hpp"
88
#include "ck_tile/builder/factory/helpers/ck/conv_elementwise_op.hpp"
99
#include "ck_tile/builder/testing/testing.hpp"
10+
#include "ck_tile/builder/testing/testing_reflect.hpp"
1011
#include "ck_tile/builder/testing/filter_extent.hpp"
1112
#include "ck_tile/builder/testing/tensor_buffer.hpp"
1213
#include "ck_tile/builder/testing/tensor_initialization.hpp"
@@ -182,6 +183,12 @@ struct Inputs<SIGNATURE>
182183
{
183184
void* input;
184185
void* weight;
186+
187+
static void reflect(const Args<SIGNATURE>& args, const auto& inspect)
188+
{
189+
inspect("input", args.make_input_descriptor(), &Inputs<SIGNATURE>::input);
190+
inspect("weight", args.make_weight_descriptor(), &Inputs<SIGNATURE>::weight);
191+
}
185192
};
186193

187194
/// @brief `Outputs` specialization for forward convolution.
@@ -194,68 +201,13 @@ template <auto SIGNATURE>
194201
struct Outputs<SIGNATURE>
195202
{
196203
void* output;
197-
};
198-
199-
/// @brief `UniqueInputs` specialization for forward convolution.
200-
///
201-
/// @tparam SIGNATURE Forward convolution signature.
202-
///
203-
/// @see UniqueInputs
204-
/// @see ValidUniqueInputs
205-
template <auto SIGNATURE>
206-
requires ValidConvSignature<SIGNATURE> && ConvDirectionIsForward<SIGNATURE>
207-
struct UniqueInputs<SIGNATURE>
208-
{
209-
DeviceBuffer input_buf;
210-
DeviceBuffer weight_buf;
211-
212-
/// @see ValidUniqueInputs
213-
Inputs<SIGNATURE> get()
214-
{
215-
return {
216-
.input = input_buf.get(),
217-
.weight = weight_buf.get(),
218-
};
219-
}
220-
};
221-
222-
/// @brief `UniqueOutputs` specialization for forward convolution.
223-
///
224-
/// @tparam SIGNATURE Forward convolution signature.
225-
///
226-
/// @see UniqueOutputs
227-
/// @see ValidUniqueOutputs
228-
template <auto SIGNATURE>
229-
requires ValidConvSignature<SIGNATURE> && ConvDirectionIsForward<SIGNATURE>
230-
struct UniqueOutputs<SIGNATURE>
231-
{
232-
DeviceBuffer output_buf;
233204

234-
/// @see ValidUniqueOutputs
235-
Outputs<SIGNATURE> get()
205+
static void reflect(const Args<SIGNATURE>& args, const auto& inspect)
236206
{
237-
return {
238-
.output = output_buf.get(),
239-
};
207+
inspect("output", args.make_output_descriptor(), &Outputs<SIGNATURE>::output);
240208
}
241209
};
242210

243-
/// @brief `alloc_inputs()` specialization for forward convolution.
244-
///
245-
/// @tparam SIGNATURE Forward convolution signature.
246-
///
247-
/// @see alloc_inputs()
248-
template <auto SIGNATURE>
249-
requires ValidConvSignature<SIGNATURE> && ConvDirectionIsForward<SIGNATURE> &&
250-
ValidUniqueInputs<SIGNATURE>
251-
UniqueInputs<SIGNATURE> alloc_inputs(const Args<SIGNATURE>& args)
252-
{
253-
return {
254-
.input_buf = alloc_tensor_buffer(args.make_input_descriptor()),
255-
.weight_buf = alloc_tensor_buffer(args.make_weight_descriptor()),
256-
};
257-
}
258-
259211
/// @brief `init_inputs()` specialization for forward convolution.
260212
///
261213
/// @tparam SIGNATURE Forward convolution signature.
@@ -269,34 +221,4 @@ void init_inputs(const Args<SIGNATURE>& args, Inputs<SIGNATURE> inputs)
269221
init_tensor_buffer_uniform_fp(inputs.weight, args.make_weight_descriptor(), -2.0f, 2.0f);
270222
}
271223

272-
/// @brief `alloc_outputs()` specialization for forward convolution.
273-
///
274-
/// @tparam SIGNATURE Forward convolution signature.
275-
///
276-
/// @see alloc_outputs()
277-
template <auto SIGNATURE>
278-
requires ValidConvSignature<SIGNATURE> && ConvDirectionIsForward<SIGNATURE> &&
279-
ValidUniqueOutputs<SIGNATURE>
280-
UniqueOutputs<SIGNATURE> alloc_outputs(const Args<SIGNATURE>& args)
281-
{
282-
return {
283-
.output_buf = alloc_tensor_buffer(args.make_output_descriptor()),
284-
};
285-
}
286-
287-
/// @brief `validate()` specialization for forward convolution.
288-
///
289-
/// @tparam SIGNATURE Forward convolution signature.
290-
///
291-
/// @see validate()
292-
template <auto SIGNATURE>
293-
requires ValidConvSignature<SIGNATURE> && ConvDirectionIsForward<SIGNATURE>
294-
ValidationReport
295-
validate(const Args<SIGNATURE>& args, Outputs<SIGNATURE> actual, Outputs<SIGNATURE> expected)
296-
{
297-
ValidationReport report;
298-
report.check("output", args.make_output_descriptor(), actual.output, expected.output);
299-
return report;
300-
}
301-
302224
} // namespace ck_tile::builder::test

experimental/builder/include/ck_tile/builder/testing/tensor_buffer.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,15 @@ inline DeviceBuffer alloc_buffer(size_t size)
8181
return DeviceBuffer(d_buf);
8282
}
8383

84+
/// @brief "Align" an offset to a multiple of a particular alignment.
85+
///
86+
/// Returns `addr` aligned to the next multiple of `alignment`.
87+
///
88+
/// @param addr The address to align.
89+
/// @param alignment The alignment.
90+
inline size_t align_fwd(size_t addr, size_t alignment)
91+
{
92+
return addr % alignment == 0 ? addr : addr - addr % alignment + alignment;
93+
}
94+
8495
} // namespace ck_tile::builder::test

experimental/builder/include/ck_tile/builder/testing/testing.hpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include <concepts>
77

8+
#include "ck_tile/builder/testing/tensor_descriptor.hpp"
9+
#include "ck_tile/builder/testing/tensor_buffer.hpp"
810
#include "ck_tile/builder/testing/validation.hpp"
911

1012
/// This file is the main header for the CK-Builder testing system. A high-level
@@ -132,8 +134,8 @@ struct Outputs;
132134
/// be created using `alloc_inputs()` and that an instance of the corresponding
133135
/// `Inputs` structure can be obtained using `.get()`.
134136
///
135-
/// @note The easiest way to implement this type is to use the `DeviceBuffer`
136-
/// type to allocate individual device buffers for each input tensor.
137+
/// @note A default implementation is provided for this type if `Inputs`
138+
/// supports `TensorReflectable`.
137139
///
138140
/// @tparam SIGNATURE The signature to specialize the structure for.
139141
///
@@ -151,8 +153,8 @@ struct UniqueInputs;
151153
/// be created using `alloc_outputs()` and that an instance of the corresponding
152154
/// `Outputs` structure can be obtained using `.get()`.
153155
///
154-
/// @note The easiest way to implement this type is to use the `DeviceBuffer`
155-
/// type to allocate individual device buffers for each output tensor.
156+
/// @note A default implementation is provided for this type if `Outputs`
157+
/// supports `TensorReflectable`.
156158
///
157159
/// @tparam SIGNATURE The signature to specialize the structure for.
158160
///
@@ -197,6 +199,12 @@ concept ValidUniqueOutputs = requires(UniqueOutputs<SIGNATURE>& inputs) {
197199
/// amount of memory required and then allocate it on the device, for example
198200
/// using `alloc_buffer` or `alloc_tensor_buffer`.
199201
///
202+
/// @note This function is explicitly deleted to generate compile errors
203+
/// for missing implementations.
204+
///
205+
/// @note A default implementation is provided for this function if `Inputs`
206+
/// supports `TensorReflectable`.
207+
///
200208
/// @tparam SIGNATURE The signature to specialize the structure for.
201209
///
202210
/// @param args The run-time arguments of the operation.
@@ -207,22 +215,22 @@ concept ValidUniqueOutputs = requires(UniqueOutputs<SIGNATURE>& inputs) {
207215
/// @see alloc_tensor_buffer()
208216
template <auto SIGNATURE>
209217
requires ValidUniqueInputs<SIGNATURE>
210-
UniqueInputs<SIGNATURE> alloc_inputs(const Args<SIGNATURE>& args);
218+
UniqueInputs<SIGNATURE> alloc_inputs(const Args<SIGNATURE>& args) = delete;
211219

212-
/// @brief Allocate inputs corresponding to a signature.
220+
/// @brief Initialize inputs corresponding to a signature.
213221
///
214222
/// The `init_inputs()` function is used to initialize pseudo-random data
215223
/// to the tensors specified in the Inputs structure. Implementors should
216224
/// fill each of the tensors in `inputs` with appropriate random data.
217225
///
226+
/// @note This function is explicitly deleted to generate compile errors
227+
/// for missing implementations.
228+
///
218229
/// @tparam SIGNATURE the signature to specialize the structure for.
219230
///
220231
/// @param args The run-time arguments of the operation.
221232
/// @param inputs The operation inputs to initialize with random data.
222233
///
223-
/// @note This function is explicitly deleted to generate compile errors
224-
/// for missing implementations.
225-
///
226234
/// @see Inputs
227235
/// @see tensor_initialization
228236
template <auto SIGNATURE>
@@ -235,13 +243,16 @@ void init_inputs(const Args<SIGNATURE>& args, Inputs<SIGNATURE> inputs) = delete
235243
/// amount of memory required and then allocate it on the device, for example
236244
/// using `alloc_buffer` or `alloc_tensor_buffer`.
237245
///
246+
/// @note This function is explicitly deleted to generate compile errors
247+
/// for missing implementations.
248+
///
249+
/// @note A default implementation is provided for this function if `Outputs`
250+
/// supports `TensorReflectable`.
251+
///
238252
/// @tparam SIGNATURE The signature to specialize the structure for.
239253
///
240254
/// @param args The run-time arguments of the operation.
241255
///
242-
/// @note This function is explicitly deleted to generate compile errors
243-
/// for missing implementations.
244-
///
245256
/// @see Outputs
246257
/// @see UniqueOutputs
247258
/// @see alloc_buffer()
@@ -262,15 +273,15 @@ UniqueInputs<SIGNATURE> alloc_outputs(const Args<SIGNATURE>& args) = delete;
262273
/// were incorrect, and where (a subset of) those elements are located within
263274
/// the tensor. See `ValidationReport` for more information about the report.
264275
///
276+
/// @note This function is explicitly deleted to generate compile errors
277+
/// for missing implementations.
278+
///
265279
/// @tparam SIGNATURE The signature to specialize the structure for.
266280
///
267281
/// @param args The run-time arguments of the operation.
268282
/// @param actual The actual results, the results of the operation to-be-tested.
269283
/// @param expected The expected results, the results of the reference implementation.
270284
///
271-
/// @note This function is explicitly deleted to generate compile errors
272-
/// for missing implementations.
273-
///
274285
/// @see ValidationReport
275286
template <auto SIGNATURE>
276287
ValidationReport validate(const Args<SIGNATURE>& args,

0 commit comments

Comments
 (0)