Skip to content

Commit 53c6ad2

Browse files
SS-JIAssjia
andauthored
[ET-VK][ez] Improve quantized convolution test case naming (#16141)
Stack from [ghstack](https://github.com/ezyang/ghstack) (oldest at bottom): * #16142 * __->__ #16141 As title - update the way the test case names are displayed in the quantized convolution test binaries so that it is more clear what is being tested. Before: ``` performance_64/32_128/128_3/3_Texture3D_Float ``` After: ``` PERF 32->64 I=128,128 k=3 Tex->Buf ``` Differential Revision: [D88702991](https://our.internmc.facebook.com/intern/diff/D88702991/) Co-authored-by: ssjia <ssjia@devvm1479.ncg0.facebook.com>
1 parent 9116df7 commit 53c6ad2

File tree

6 files changed

+209
-122
lines changed

6 files changed

+209
-122
lines changed

backends/vulkan/test/custom_ops/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ if(TARGET vulkan_backend)
4848

4949
# Prototyping utility files
5050
set(PROTOTYPING_UTILS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR})
51-
set(PROTOTYPING_UTILS_CPP ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp)
51+
set(PROTOTYPING_UTILS_CPP ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
52+
${CMAKE_CURRENT_SOURCE_DIR}/conv2d_utils.cpp
53+
)
5254

5355
# Prototyping shaders
5456
message(STATUS "shader stuff")

backends/vulkan/test/custom_ops/conv2d_utils.cpp

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,87 @@
66

77
#include "conv2d_utils.h"
88

9-
// Implementation file for conv2d utilities.
10-
// Currently all functionality is implemented inline in the header.
9+
namespace executorch {
10+
namespace vulkan {
11+
namespace prototyping {
12+
13+
std::string make_test_case_conv_params_suffix(const Conv2dConfig& config) {
14+
std::string suffix;
15+
// Only print groups if not equal to 1
16+
if (config.groups != 1) {
17+
suffix += "g=" + std::to_string(config.groups);
18+
suffix += " ";
19+
}
20+
21+
suffix += "k=";
22+
if (config.kernel.h == config.kernel.w) {
23+
suffix += std::to_string(config.kernel.w);
24+
} else {
25+
suffix +=
26+
std::to_string(config.kernel.w) + "," + std::to_string(config.kernel.h);
27+
}
28+
// Only print stride if either dimension is not 1
29+
if (config.stride.h > 1 || config.stride.w > 1) {
30+
suffix += ",s=";
31+
if (config.stride.h == config.stride.w) {
32+
suffix += std::to_string(config.stride.w);
33+
} else {
34+
suffix += std::to_string(config.stride.w) + "," +
35+
std::to_string(config.stride.h);
36+
}
37+
}
38+
// Only print padding if either dimension is not 1
39+
if (config.padding.h != 1 || config.padding.w != 1) {
40+
suffix += ",p=";
41+
if (config.padding.h == config.padding.w) {
42+
suffix += std::to_string(config.padding.w);
43+
} else {
44+
suffix += std::to_string(config.padding.w) + "," +
45+
std::to_string(config.padding.h);
46+
}
47+
}
48+
// Only print dilation if either dimension is not 1
49+
if (config.dilation.h != 1 || config.dilation.w != 1) {
50+
suffix += ",d=";
51+
if (config.dilation.h == config.dilation.w) {
52+
suffix += std::to_string(config.dilation.w);
53+
} else {
54+
suffix += std::to_string(config.dilation.w) + "," +
55+
std::to_string(config.dilation.h);
56+
}
57+
}
58+
return suffix;
59+
}
60+
61+
std::string to_string(const vkcompute::utils::StorageType storage_type) {
62+
switch (storage_type) {
63+
case vkcompute::utils::kTexture3D:
64+
return "Tex";
65+
case vkcompute::utils::kTexture2D:
66+
return "Tex2D";
67+
case vkcompute::utils::kBuffer:
68+
return "Buf";
69+
}
70+
}
71+
72+
std::string make_test_case_name(
73+
const Conv2dConfig& config,
74+
const bool is_performance,
75+
const vkcompute::utils::StorageType fp_storage_type,
76+
const vkcompute::utils::StorageType int8_storage_type) {
77+
std::string test_case_name = is_performance ? "PERF " : "ACCU ";
78+
test_case_name += std::to_string(config.channels.in) + "->" +
79+
std::to_string(config.channels.out) +
80+
" I=" + std::to_string(config.input_size.h) + "," +
81+
std::to_string(config.input_size.w) + " " +
82+
make_test_case_conv_params_suffix(config);
83+
84+
test_case_name +=
85+
" " + to_string(fp_storage_type) + "->" + to_string(int8_storage_type);
86+
87+
return test_case_name;
88+
}
89+
90+
} // namespace prototyping
91+
} // namespace vulkan
92+
} // namespace executorch

backends/vulkan/test/custom_ops/conv2d_utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#pragma once
88

9+
#include <executorch/backends/vulkan/runtime/api/api.h>
10+
911
#include <cstdint>
1012
#include <string>
1113

@@ -83,6 +85,12 @@ struct Conv2dConfig {
8385
}
8486
};
8587

88+
std::string make_test_case_name(
89+
const Conv2dConfig& config,
90+
const bool is_performance,
91+
const vkcompute::utils::StorageType fp_storage_type,
92+
const vkcompute::utils::StorageType int8_storage_type);
93+
8694
} // namespace prototyping
8795
} // namespace vulkan
8896
} // namespace executorch

backends/vulkan/test/custom_ops/q8ta_q8csw_q8to_conv2d.cpp

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44
// This source code is licensed under the BSD-style license found in the
55
// LICENSE file in the root directory of this source tree.
66

7-
#include <executorch/backends/vulkan/runtime/graph/ops/impl/Common.h>
8-
#include <executorch/backends/vulkan/runtime/graph/ops/utils/ShaderNameUtils.h>
97
#include <iostream>
108
#include <vector>
11-
#include "conv2d_utils.h"
12-
#include "utils.h"
9+
10+
#include <executorch/backends/vulkan/runtime/graph/ops/impl/Common.h>
11+
#include <executorch/backends/vulkan/runtime/graph/ops/utils/ShaderNameUtils.h>
1312

1413
#include <executorch/backends/vulkan/runtime/graph/ops/impl/Staging.h>
1514

15+
#include "conv2d_utils.h"
16+
#include "utils.h"
17+
1618
// #define DEBUG_MODE
1719

1820
using namespace executorch::vulkan::prototyping;
@@ -24,22 +26,14 @@ static constexpr int64_t kRefDimSizeLimit = 100;
2426
// Utility function to create a test case from a Conv2dConfig
2527
TestCase create_test_case_from_config(
2628
const Conv2dConfig& config,
27-
utils::StorageType storage_type,
2829
vkapi::ScalarType input_dtype,
29-
utils::StorageType interm_storage_type) {
30+
utils::StorageType fp_storage_type,
31+
utils::StorageType int8_storage_type) {
3032
TestCase test_case;
31-
32-
// Create a descriptive name for the test case
33-
std::string storage_str =
34-
(storage_type == utils::kTexture3D) ? "Texture3D" : "Buffer";
35-
std::string dtype_str = (input_dtype == vkapi::kFloat) ? "Float" : "Half";
36-
37-
std::string test_name =
38-
config.test_case_name + "_" + storage_str + "_" + dtype_str;
39-
test_case.set_name(test_name);
33+
test_case.set_name(config.test_case_name);
4034

4135
std::string operator_suffix = ".test";
42-
if (interm_storage_type == utils::kTexture3D) {
36+
if (int8_storage_type == utils::kTexture3D) {
4337
operator_suffix += "_texture";
4438
} else {
4539
operator_suffix += "_buffer";
@@ -57,15 +51,15 @@ TestCase create_test_case_from_config(
5751
std::vector<int64_t> input_size = {
5852
1, config.channels.in, config.input_size.h, config.input_size.w};
5953

60-
utils::GPUMemoryLayout io_memory_layout = storage_type == utils::kBuffer
54+
utils::GPUMemoryLayout fp_memory_layout = fp_storage_type == utils::kBuffer
6155
? utils::kWidthPacked
6256
: utils::kChannelsPacked;
6357

6458
ValueSpec input_tensor(
6559
input_size,
6660
input_dtype,
67-
storage_type,
68-
io_memory_layout,
61+
fp_storage_type,
62+
fp_memory_layout,
6963
#ifdef DEBUG_MODE
7064
DataGenType::RANDOM
7165
#else
@@ -93,7 +87,7 @@ TestCase create_test_case_from_config(
9387
ValueSpec quantized_weight(
9488
weight_size,
9589
vkapi::kChar, // int8 for quantized weights
96-
storage_type,
90+
fp_storage_type,
9791
utils::kWidthPacked,
9892
DataGenType::RANDINT8);
9993
quantized_weight.set_constant(true);
@@ -108,15 +102,15 @@ TestCase create_test_case_from_config(
108102
ValueSpec weight_scales(
109103
{aligned_out_channels}, // Per output channel
110104
input_dtype,
111-
storage_type,
105+
fp_storage_type,
112106
utils::kWidthPacked,
113107
DataGenType::RANDOM_SCALES);
114108
weight_scales.set_constant(true);
115109

116110
ValueSpec weight_sums(
117111
{aligned_out_channels}, // Per output channel
118112
vkapi::kInt,
119-
storage_type,
113+
fp_storage_type,
120114
utils::kWidthPacked,
121115
DataGenType::ZEROS);
122116
weight_sums.set_constant(true);
@@ -129,13 +123,12 @@ TestCase create_test_case_from_config(
129123
ValueSpec bias(
130124
{aligned_out_channels}, // Per output channel
131125
input_dtype,
132-
storage_type,
126+
fp_storage_type,
133127
utils::kWidthPacked,
134128
DataGenType::ZEROS);
135129
bias.set_constant(true);
136130

137131
// Output quantization parameters
138-
// float output_scale_val = 0.01432;
139132
float output_scale_val = 0.05314;
140133
ValueSpec output_scale(output_scale_val);
141134

@@ -157,8 +150,8 @@ TestCase create_test_case_from_config(
157150
ValueSpec output(
158151
{1, config.channels.out, H_out, W_out},
159152
input_dtype,
160-
storage_type,
161-
io_memory_layout,
153+
fp_storage_type,
154+
fp_memory_layout,
162155
DataGenType::ZEROS);
163156

164157
// Add all specs to test case for q8ta_q8csw_q8to operation
@@ -200,18 +193,16 @@ std::vector<TestCase> generate_quantized_conv2d_easy_cases() {
200193
};
201194
config.op_name = "conv2d_q8ta_q8csw_q8to";
202195

203-
// Test with both storage types and data types for completeness
204196
std::vector<utils::StorageType> storage_types = {
205197
utils::kTexture3D, utils::kBuffer};
206-
std::vector<vkapi::ScalarType> float_types = {vkapi::kFloat};
207198

208199
// Generate test cases for each combination
209-
for (const auto& storage_type : storage_types) {
210-
for (const auto& input_dtype : float_types) {
200+
for (const utils::StorageType fp_storage_type : storage_types) {
201+
for (const utils::StorageType int8_storage_type : storage_types) {
202+
config.test_case_name = make_test_case_name(
203+
config, false, fp_storage_type, int8_storage_type);
211204
test_cases.push_back(create_test_case_from_config(
212-
config, storage_type, input_dtype, utils::kBuffer));
213-
test_cases.push_back(create_test_case_from_config(
214-
config, storage_type, input_dtype, utils::kTexture3D));
205+
config, vkapi::kFloat, fp_storage_type, int8_storage_type));
215206
}
216207
}
217208

@@ -221,6 +212,9 @@ std::vector<TestCase> generate_quantized_conv2d_easy_cases() {
221212
// Generate test cases for quantized conv2d operation
222213
std::vector<TestCase> generate_quantized_conv2d_test_cases() {
223214
std::vector<TestCase> test_cases;
215+
if (!vkcompute::api::context()->adapter_ptr()->supports_int8_dot_product()) {
216+
return test_cases;
217+
}
224218

225219
std::vector<Conv2dConfig> configs = {
226220
// Pointwise convolutions: kernel size 1x1
@@ -317,7 +311,7 @@ std::vector<TestCase> generate_quantized_conv2d_test_cases() {
317311
Padding(2, 2),
318312
Dilation(1, 1),
319313
4},
320-
// Performance cases (pointwise)
314+
// Performance cases (pointwise - will use im2col)
321315
{OutInChannels(128, 128),
322316
InputSize2D(128, 128),
323317
KernelSize(1, 1),
@@ -332,7 +326,7 @@ std::vector<TestCase> generate_quantized_conv2d_test_cases() {
332326
Padding(0, 0),
333327
Dilation(1, 1),
334328
1},
335-
// Performance cases (general 2d convs)
329+
// Performance cases (3x3 convs - will use im2col)
336330
{OutInChannels(32, 3),
337331
InputSize2D(256, 256),
338332
KernelSize(3, 3),
@@ -354,6 +348,21 @@ std::vector<TestCase> generate_quantized_conv2d_test_cases() {
354348
Padding(1, 1),
355349
Dilation(1, 1),
356350
1},
351+
// Performance cases (grouped convs)
352+
{OutInChannels(64, 64),
353+
InputSize2D(128, 128),
354+
KernelSize(3, 3),
355+
Stride(1, 1),
356+
Padding(1, 1),
357+
Dilation(1, 1),
358+
2},
359+
{OutInChannels(96, 96),
360+
InputSize2D(128, 128),
361+
KernelSize(3, 3),
362+
Stride(2, 2),
363+
Padding(1, 1),
364+
Dilation(1, 1),
365+
3},
357366
{OutInChannels(128, 128),
358367
InputSize2D(128, 128),
359368
KernelSize(5, 5),
@@ -368,32 +377,19 @@ std::vector<TestCase> generate_quantized_conv2d_test_cases() {
368377

369378
// Generate test cases for each combination
370379
for (auto& config : configs) {
371-
for (const auto& storage_type : storage_types) {
372-
// Generate test case name programmatically
373-
bool is_performance = config.channels.out > kRefDimSizeLimit ||
374-
config.channels.in > kRefDimSizeLimit ||
375-
config.input_size.h > kRefDimSizeLimit ||
376-
config.input_size.w > kRefDimSizeLimit;
377-
std::string prefix = is_performance ? "performance_" : "correctness_";
378-
std::string suffix = std::to_string(config.channels.out) + "/" +
379-
std::to_string(config.channels.in) + "_" +
380-
std::to_string(config.input_size.h) + "/" +
381-
std::to_string(config.input_size.w) + "_" +
382-
std::to_string(config.kernel.h) + "/" +
383-
std::to_string(config.kernel.w);
384-
385-
config.op_name = "conv2d_q8ta_q8csw_q8to";
386-
config.test_case_name = prefix + suffix;
387-
388-
// Only test q8ta_q8csw_q8to if the int8 dot product extension is
389-
// supported
390-
if (vkcompute::api::context()
391-
->adapter_ptr()
392-
->supports_int8_dot_product()) {
393-
test_cases.push_back(create_test_case_from_config(
394-
config, storage_type, vkapi::kFloat, utils::kBuffer));
380+
bool is_performance = config.channels.out > kRefDimSizeLimit ||
381+
config.channels.in > kRefDimSizeLimit ||
382+
config.input_size.h > kRefDimSizeLimit ||
383+
config.input_size.w > kRefDimSizeLimit;
384+
385+
config.op_name = "conv2d_q8ta_q8csw_q8to";
386+
387+
for (const utils::StorageType fp_storage_type : storage_types) {
388+
for (const utils::StorageType int8_storage_type : storage_types) {
389+
config.test_case_name = make_test_case_name(
390+
config, is_performance, fp_storage_type, int8_storage_type);
395391
test_cases.push_back(create_test_case_from_config(
396-
config, storage_type, vkapi::kFloat, utils::kTexture3D));
392+
config, vkapi::kFloat, fp_storage_type, int8_storage_type));
397393
}
398394
}
399395
}

0 commit comments

Comments
 (0)