Skip to content

Commit c9e1b84

Browse files
Abhi-hppfacebook-github-bot
authored andcommitted
Optimized axis map (#7886)
Summary: Add a flag to optimize the axis map layout to be in descending order of axis size. The default is still the same. Reviewed By: SS-JIA Differential Revision: D67692960
1 parent 8ec08f9 commit c9e1b84

File tree

7 files changed

+109
-34
lines changed

7 files changed

+109
-34
lines changed

backends/vulkan/runtime/api/containers/Tensor.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#include <executorch/backends/vulkan/runtime/api/containers/Tensor.h>
10+
#include <cassert>
1011
#include <cstring>
1112

1213
namespace vkcompute {
@@ -99,12 +100,31 @@ std::vector<int64_t> calculate_strides(
99100
*
100101
* The axis mapping allows for permuted views of texture-backed tensors.
101102
*/
102-
std::vector<int64_t> default_axis_map() {
103-
// Currently, all compute shaders have an assumption that the channels dim is
104-
// used to combine with the batch dim of a tensor. However, once dim mapping
105-
// is integrated into the tensor indexing logic for each compute shader, we
106-
// can be more flexible with mapping the batch dim to different texture axes
107-
// in order to improve performance or memory footprint.
103+
std::vector<int64_t> calculate_axis_map(
104+
const std::vector<int64_t>& sizes,
105+
utils::AxisMapLayout axis_map_layout) {
106+
if (axis_map_layout == utils::AxisMapLayout::OPTIMIZED) {
107+
std::vector<int64_t> axis_map(sizes.size() + 1);
108+
std::iota(axis_map.begin(), axis_map.end() - 1, 0);
109+
110+
std::stable_sort(
111+
axis_map.begin(), axis_map.end() - 1, [&sizes](size_t i1, size_t i2) {
112+
return sizes[i1] < sizes[i2];
113+
});
114+
115+
assert(axis_map.size() > 0);
116+
// Find the index of the channel dimension
117+
for (size_t i = 0; i < axis_map.size() - 1; ++i) {
118+
assert(sizes.size() > axis_map[i]);
119+
if (sizes[axis_map[i]] == 2) {
120+
axis_map.back() = i;
121+
break;
122+
}
123+
}
124+
125+
return axis_map;
126+
}
127+
// default
108128
return {0, 1, 2, 2};
109129
}
110130

@@ -439,13 +459,14 @@ vTensor::vTensor(
439459
const vkapi::ScalarType dtype,
440460
const utils::StorageType storage_type,
441461
const utils::GPUMemoryLayout memory_layout,
442-
const bool allocate_memory)
462+
const bool allocate_memory,
463+
const utils::AxisMapLayout axis_map_layout)
443464
: dtype_(dtype),
444465
// Calculate tensor metadata
445466
sizes_(sizes.begin(), sizes.end()),
446467
packed_dim_(utils::to_packed_dim<int32_t>(memory_layout)),
447468
dim_order_(calculate_dim_order(sizes_.size(), packed_dim_)),
448-
axis_map_(default_axis_map()),
469+
axis_map_(calculate_axis_map(sizes_, axis_map_layout)),
449470
strides_(calculate_strides(sizes, dim_order_)),
450471
padded_sizes_{calculate_padded_sizes(sizes, packed_dim_)},
451472
unsqueezed_strides_{
@@ -484,13 +505,14 @@ vTensor::vTensor(
484505
vTensor::vTensor(
485506
Context* context,
486507
const vkapi::VulkanImage& image,
487-
const utils::GPUMemoryLayout memory_layout)
508+
const utils::GPUMemoryLayout memory_layout,
509+
const utils::AxisMapLayout axis_map_layout)
488510
: dtype_(vkapi::element_scalartype(image.format())),
489511
// Calculate tensor metadata
490512
sizes_(calculate_sizes(image, memory_layout)),
491513
packed_dim_(utils::to_packed_dim<int32_t>(memory_layout)),
492514
dim_order_(),
493-
axis_map_(default_axis_map()),
515+
axis_map_(calculate_axis_map(sizes_, axis_map_layout)),
494516
strides_(),
495517
padded_sizes_(calculate_padded_sizes(sizes_, packed_dim_)),
496518
unsqueezed_strides_(),
@@ -547,7 +569,7 @@ vTensor::vTensor(
547569
sizes_(sizes.begin(), sizes.end()),
548570
packed_dim_(other.packed_dim_),
549571
dim_order_(dim_order.begin(), dim_order.end()),
550-
axis_map_(default_axis_map()),
572+
axis_map_(calculate_axis_map(sizes_, utils::kDefaultAxisMap)),
551573
strides_(calculate_strides(sizes_, dim_order_)),
552574
padded_sizes_{calculate_padded_sizes(sizes, packed_dim_)},
553575
unsqueezed_strides_{

backends/vulkan/runtime/api/containers/Tensor.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,16 @@ class vTensor final {
183183
const vkapi::ScalarType dtype,
184184
const utils::StorageType storage_type = utils::kTexture3D,
185185
const utils::GPUMemoryLayout memory_layout = utils::kChannelsPacked,
186-
const bool allocate_memory = true);
186+
const bool allocate_memory = true,
187+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
187188

188189
vTensor(const vTensor& other) = delete;
189190

190191
explicit vTensor(
191192
Context* context,
192193
const vkapi::VulkanImage& image,
193-
const utils::GPUMemoryLayout memory_layout = utils::kChannelsPacked);
194+
const utils::GPUMemoryLayout memory_layout = utils::kChannelsPacked,
195+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
194196

195197
/*
196198
* This constructor allows for the creation of a vTensor that references the

backends/vulkan/runtime/graph/ComputeGraph.cpp

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,20 @@ ValueRef ComputeGraph::add_tensor(
239239
const vkapi::ScalarType dtype,
240240
const utils::StorageType storage_type,
241241
const utils::GPUMemoryLayout memory_layout,
242-
const int64_t shared_object_idx) {
242+
const int64_t shared_object_idx,
243+
const utils::AxisMapLayout axis_map_layout) {
243244
bool allocate_memory = shared_object_idx < 0;
244245

245246
ValueRef idx(static_cast<int>(values_.size()));
246247
check_no_active_value_ptrs();
247248
values_.emplace_back(api::vTensor(
248-
context(), sizes, dtype, storage_type, memory_layout, allocate_memory));
249+
context(),
250+
sizes,
251+
dtype,
252+
storage_type,
253+
memory_layout,
254+
allocate_memory,
255+
axis_map_layout));
249256

250257
if (!allocate_memory) {
251258
get_shared_object(shared_object_idx).add_user(this, idx);
@@ -257,44 +264,70 @@ ValueRef ComputeGraph::add_tensor(
257264
const std::vector<int64_t>& sizes,
258265
const vkapi::ScalarType dtype,
259266
const utils::StorageType storage_type,
260-
const int64_t shared_object_idx) {
267+
const int64_t shared_object_idx,
268+
const utils::AxisMapLayout axis_map_layout) {
261269
return add_tensor(
262270
sizes,
263271
dtype,
264272
storage_type,
265273
suggested_memory_layout(sizes),
266-
shared_object_idx);
274+
shared_object_idx,
275+
axis_map_layout);
267276
}
268277

269278
ValueRef ComputeGraph::add_tensor(
270279
const std::vector<int64_t>& sizes,
271280
const vkapi::ScalarType dtype,
272281
const utils::GPUMemoryLayout memory_layout,
273-
const int64_t shared_object_idx) {
282+
const int64_t shared_object_idx,
283+
const utils::AxisMapLayout axis_map_layout) {
274284
return add_tensor(
275-
sizes, dtype, suggested_storage_type(), memory_layout, shared_object_idx);
285+
sizes,
286+
dtype,
287+
suggested_storage_type(),
288+
memory_layout,
289+
shared_object_idx,
290+
axis_map_layout);
276291
}
277292

278293
ValueRef ComputeGraph::add_tensor_like(
279294
const ValueRef idx,
280295
const utils::StorageType storage_type,
281-
const utils::GPUMemoryLayout memory_layout) {
282-
return add_tensor(sizes_of(idx), dtype_of(idx), storage_type, memory_layout);
296+
const utils::GPUMemoryLayout memory_layout,
297+
const utils::AxisMapLayout axis_map_layout) {
298+
return add_tensor(
299+
sizes_of(idx),
300+
dtype_of(idx),
301+
storage_type,
302+
memory_layout,
303+
-1,
304+
axis_map_layout);
283305
}
284306

285307
ValueRef ComputeGraph::add_tensor_like(
286308
const ValueRef idx,
287-
const utils::GPUMemoryLayout memory_layout) {
309+
const utils::GPUMemoryLayout memory_layout,
310+
const utils::AxisMapLayout axis_map_layout) {
288311
return add_tensor(
289-
sizes_of(idx), dtype_of(idx), storage_type_of(idx), memory_layout);
312+
sizes_of(idx),
313+
dtype_of(idx),
314+
storage_type_of(idx),
315+
memory_layout,
316+
-1,
317+
axis_map_layout);
290318
}
291319

292320
ValueRef ComputeGraph::add_tensor(
293321
const std::vector<int64_t>& sizes,
294322
const vkapi::ScalarType dtype,
295-
const int64_t shared_object_idx) {
323+
const int64_t shared_object_idx,
324+
const utils::AxisMapLayout axis_map_layout) {
296325
return add_tensor(
297-
sizes, dtype, suggested_memory_layout(sizes), shared_object_idx);
326+
sizes,
327+
dtype,
328+
suggested_memory_layout(sizes),
329+
shared_object_idx,
330+
axis_map_layout);
298331
}
299332

300333
ValueRef ComputeGraph::add_tensor(const vkapi::VulkanImage& image) {

backends/vulkan/runtime/graph/ComputeGraph.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ class ComputeGraph final {
461461
const vkapi::ScalarType dtype,
462462
const utils::StorageType storage_type,
463463
const utils::GPUMemoryLayout memory_layout,
464-
const int64_t shared_object_idx = -1);
464+
const int64_t shared_object_idx = -1,
465+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
465466

466467
/*
467468
* Add a `api::vTensor` value to the graph with the specified properties. The
@@ -471,7 +472,8 @@ class ComputeGraph final {
471472
const std::vector<int64_t>& sizes,
472473
const vkapi::ScalarType dtype,
473474
const utils::StorageType storage_type,
474-
const int64_t shared_object_idx = -1);
475+
const int64_t shared_object_idx = -1,
476+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
475477

476478
/*
477479
* Add a `api::vTensor` value to the graph with the specified properties. The
@@ -481,7 +483,8 @@ class ComputeGraph final {
481483
const std::vector<int64_t>& sizes,
482484
const vkapi::ScalarType dtype,
483485
const utils::GPUMemoryLayout memory_layout,
484-
const int64_t shared_object_idx = -1);
486+
const int64_t shared_object_idx = -1,
487+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
485488

486489
/*
487490
* Add a `api::vTensor` value to the graph with the specified properties. The
@@ -491,7 +494,8 @@ class ComputeGraph final {
491494
ValueRef add_tensor(
492495
const std::vector<int64_t>& sizes,
493496
const vkapi::ScalarType dtype,
494-
const int64_t shared_object_idx = -1);
497+
const int64_t shared_object_idx = -1,
498+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
495499

496500
/*
497501
* Add a `api::vTensor` value to the graph with the specified image.
@@ -504,15 +508,17 @@ class ComputeGraph final {
504508
ValueRef add_tensor_like(
505509
const ValueRef vref,
506510
const utils::StorageType storage_type,
507-
const utils::GPUMemoryLayout memory_layout);
511+
const utils::GPUMemoryLayout memory_layout,
512+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
508513

509514
/*
510515
* Add a `api::vTensor` value to the graph with the properties of `vref`. The
511516
* suggested storage type will be used to construct the `api::vTensor`.
512517
*/
513518
ValueRef add_tensor_like(
514519
const ValueRef vref,
515-
const utils::GPUMemoryLayout memory_layout);
520+
const utils::GPUMemoryLayout memory_layout,
521+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
516522

517523
/*
518524
* Use the copy constructor of `api::vTensor` to create a "view" of the

backends/vulkan/runtime/graph/ops/impl/Staging.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,14 @@ ValueRef prepack_standard(
146146
const ValueRef tensor_data,
147147
const utils::StorageType storage_type,
148148
const utils::GPUMemoryLayout layout,
149-
const bool passthrough) {
149+
const bool passthrough,
150+
const utils::AxisMapLayout axis_map_layout) {
150151
if (passthrough && graph.val_is_tensor(tensor_data)) {
151152
return tensor_data;
152153
}
153154
VK_CHECK_COND(graph.val_is_tref(tensor_data));
154-
ValueRef tensor = graph.add_tensor_like(tensor_data, storage_type, layout);
155+
ValueRef tensor =
156+
graph.add_tensor_like(tensor_data, storage_type, layout, axis_map_layout);
155157
add_prepack_standard_node(graph, tensor_data, tensor);
156158
return tensor;
157159
}

backends/vulkan/runtime/graph/ops/impl/Staging.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ ValueRef prepack_standard(
4848
const ValueRef tensor_data,
4949
const utils::StorageType storage_type,
5050
const utils::GPUMemoryLayout layout,
51-
const bool passthrough = false);
51+
const bool passthrough = false,
52+
const utils::AxisMapLayout axis_map_layout = utils::kDefaultAxisMap);
5253

5354
/*
5455
* Equivalent to `prepack_standard()` function, except the `storage_type` and

backends/vulkan/runtime/utils/StorageUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,14 @@ inline std::ostream& operator<<(
146146
return os;
147147
}
148148

149+
enum class AxisMapLayout : uint8_t {
150+
DEFAULT = 0u,
151+
OPTIMIZED = 1u,
152+
};
153+
154+
constexpr AxisMapLayout kDefaultAxisMap = AxisMapLayout::DEFAULT;
155+
156+
constexpr AxisMapLayout kOptimizedAxisMap = AxisMapLayout::OPTIMIZED;
157+
149158
} // namespace utils
150159
} // namespace vkcompute

0 commit comments

Comments
 (0)