Skip to content

Commit a3455d9

Browse files
pytorchbotSS-JIA
andauthored
[ET-VK] Add utility functions to get pipeline executable properties
## Context Leverage the [VK_KHR_pipeline_executable_properties](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_pipeline_executable_properties.html) extension to view shader compilation stats and potentially compiled IR that is exposed by the driver. This information can be useful during shader optimization to get more insight into what the compiled shader is actually doing. Differential Revision: [D69125488](https://our.internmc.facebook.com/intern/diff/D69125488/) ghstack-source-id: 264624416 Pull Request resolved: #8182 Co-authored-by: Stephen Jia <[email protected]>
1 parent 71dff79 commit a3455d9

File tree

5 files changed

+269
-1
lines changed

5 files changed

+269
-1
lines changed

backends/vulkan/runtime/api/Context.cpp

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

99
#include <executorch/backends/vulkan/runtime/api/Context.h>
1010

11+
#ifdef VULKAN_DEBUG
12+
#include <iomanip>
13+
#include <iostream>
14+
#endif // VULKAN_DEBUG
15+
1116
#ifndef VULKAN_DESCRIPTOR_POOL_SIZE
1217
#define VULKAN_DESCRIPTOR_POOL_SIZE 1024u
1318
#endif
@@ -261,5 +266,220 @@ Context* context() {
261266
return context.get();
262267
}
263268

269+
#ifdef VULKAN_DEBUG
270+
271+
#ifdef VK_KHR_pipeline_executable_properties
272+
273+
VkPipeline Context::get_shader_pipeline(
274+
const vkapi::ShaderInfo& shader,
275+
const vkapi::SpecVarList& spec_constants) {
276+
const uint32_t push_constants_size = 128u;
277+
278+
VkDescriptorSetLayout shader_layout =
279+
shader_layout_cache().retrieve(shader.kernel_layout);
280+
VkPipelineLayout pipeline_layout =
281+
pipeline_layout_cache().retrieve(shader_layout, push_constants_size);
282+
283+
vkapi::SpecVarList spec_constants_full_list = {4u, 4u, 1u};
284+
spec_constants_full_list.append(spec_constants);
285+
286+
VkPipeline pipeline = pipeline_cache().retrieve(
287+
{pipeline_layout,
288+
shader_cache().retrieve(shader),
289+
spec_constants_full_list});
290+
291+
return pipeline;
292+
}
293+
294+
std::vector<VkPipelineExecutablePropertiesKHR>
295+
Context::get_pipeline_executable_props(const VkPipeline pipeline) {
296+
VkPipelineInfoKHR pipeline_info{
297+
VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
298+
nullptr,
299+
pipeline,
300+
};
301+
302+
uint32_t shader_props_count = 0u;
303+
vkGetPipelineExecutablePropertiesKHR(
304+
device(), &pipeline_info, &shader_props_count, nullptr);
305+
306+
std::vector<VkPipelineExecutablePropertiesKHR> pipeline_props(
307+
shader_props_count);
308+
for (int i = 0; i < shader_props_count; i++) {
309+
pipeline_props.at(i).sType =
310+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
311+
pipeline_props.at(i).pNext = nullptr;
312+
}
313+
vkGetPipelineExecutablePropertiesKHR(
314+
device(), &pipeline_info, &shader_props_count, pipeline_props.data());
315+
316+
return pipeline_props;
317+
}
318+
319+
std::tuple<
320+
std::vector<VkPipelineExecutableInternalRepresentationKHR>,
321+
std::vector<std::vector<char>>>
322+
Context::get_shader_executable_irs(
323+
const VkPipeline pipeline,
324+
const uint32_t pipeline_exec_idx) {
325+
VkPipelineExecutableInfoKHR exec_info{
326+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
327+
nullptr,
328+
pipeline,
329+
pipeline_exec_idx,
330+
};
331+
332+
uint32_t ir_count;
333+
VK_CHECK(vkGetPipelineExecutableInternalRepresentationsKHR(
334+
device(), &exec_info, &ir_count, nullptr));
335+
336+
std::vector<VkPipelineExecutableInternalRepresentationKHR> irs(ir_count);
337+
for (int i = 0; i < ir_count; i++) {
338+
irs.at(i).sType =
339+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR;
340+
irs.at(i).pNext = nullptr;
341+
irs.at(i).pData = nullptr;
342+
}
343+
VK_CHECK(vkGetPipelineExecutableInternalRepresentationsKHR(
344+
device(), &exec_info, &ir_count, irs.data()));
345+
346+
std::vector<std::vector<char>> irs_data(ir_count);
347+
for (int i = 0; i < ir_count; i++) {
348+
irs_data.at(i).resize(irs.at(i).dataSize);
349+
irs.at(i).pData = irs_data.at(i).data();
350+
}
351+
VK_CHECK(vkGetPipelineExecutableInternalRepresentationsKHR(
352+
device(), &exec_info, &ir_count, irs.data()));
353+
354+
return std::make_tuple(irs, irs_data);
355+
}
356+
357+
std::vector<VkPipelineExecutableStatisticKHR>
358+
Context::get_shader_executable_stats(
359+
const VkPipeline pipeline,
360+
const uint32_t pipeline_exec_idx) {
361+
VkPipelineExecutableInfoKHR exec_info{
362+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
363+
nullptr,
364+
pipeline,
365+
pipeline_exec_idx,
366+
};
367+
368+
uint32_t stats_count;
369+
VK_CHECK(vkGetPipelineExecutableStatisticsKHR(
370+
device(), &exec_info, &stats_count, NULL));
371+
372+
std::vector<VkPipelineExecutableStatisticKHR> shader_stats(stats_count);
373+
for (int i = 0; i < stats_count; i++) {
374+
shader_stats.at(i).sType =
375+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
376+
shader_stats.at(i).pNext = nullptr;
377+
}
378+
vkGetPipelineExecutableStatisticsKHR(
379+
device(), &exec_info, &stats_count, shader_stats.data());
380+
381+
return shader_stats;
382+
}
383+
384+
std::ostream& operator<<(
385+
std::ostream& os,
386+
const VkPipelineExecutablePropertiesKHR& props) {
387+
os << std::left << std::setw(10) << "name: " << props.name << std::endl;
388+
os << std::left << std::setw(10) << "descr: " << props.description
389+
<< std::endl;
390+
os << std::left << std::setw(10) << "subgroup: " << props.subgroupSize
391+
<< std::endl;
392+
393+
return os;
394+
}
395+
396+
std::ostream& operator<<(
397+
std::ostream& os,
398+
const VkPipelineExecutableInternalRepresentationKHR& ir) {
399+
os << std::left << std::setw(10) << "descr: " << ir.description << std::endl;
400+
os << std::left << std::setw(10) << "isText: " << ir.isText << std::endl;
401+
os << std::left << std::setw(10) << "size: " << ir.dataSize << std::endl;
402+
if (ir.isText) {
403+
os << "text:" << std::endl;
404+
char* str = (char*)ir.pData;
405+
os << str << std::endl;
406+
}
407+
return os;
408+
}
409+
410+
std::ostream& operator<<(
411+
std::ostream& os,
412+
VkPipelineExecutableStatisticKHR& stat) {
413+
os << stat.name << ": ";
414+
switch (stat.format) {
415+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
416+
os << (stat.value.b32 ? "true" : "false") << std::endl;
417+
break;
418+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
419+
os << stat.value.i64 << std::endl;
420+
break;
421+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
422+
os << stat.value.u64 << std::endl;
423+
break;
424+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
425+
os << stat.value.f64 << std::endl;
426+
break;
427+
default:
428+
break;
429+
}
430+
os << " " << stat.description << std::endl;
431+
return os;
432+
}
433+
434+
std::ostream& operator<<(
435+
std::ostream& os,
436+
std::vector<VkPipelineExecutableStatisticKHR>& shader_stats) {
437+
for (int i = 0; i < shader_stats.size(); i++) {
438+
VkPipelineExecutableStatisticKHR& stat = shader_stats.at(i);
439+
os << stat;
440+
}
441+
return os;
442+
}
443+
444+
void Context::print_shader_executable_properties(
445+
const vkapi::ShaderInfo& shader,
446+
const vkapi::SpecVarList& spec_constants) {
447+
VkPipeline pipeline = get_shader_pipeline(shader, spec_constants);
448+
449+
std::vector<VkPipelineExecutablePropertiesKHR> pipeline_props_list =
450+
get_pipeline_executable_props(pipeline);
451+
452+
VK_CHECK_COND(pipeline_props_list.size() == 1u);
453+
454+
std::cout << pipeline_props_list.at(0) << std::endl;
455+
456+
std::tuple<
457+
std::vector<VkPipelineExecutableInternalRepresentationKHR>,
458+
std::vector<std::vector<char>>>
459+
irs_and_irs_data = get_shader_executable_irs(pipeline, 0u);
460+
461+
std::vector<VkPipelineExecutableInternalRepresentationKHR>& irs =
462+
std::get<0>(irs_and_irs_data);
463+
464+
std::cout << "Found " << irs.size() << " IRs" << std::endl << std::endl;
465+
for (int i = 0; i < irs.size(); i++) {
466+
std::cout << "====== IR " << i << ": " << irs.at(i).name
467+
<< " ======" << std::endl;
468+
std::cout << irs.at(i) << std::endl;
469+
}
470+
471+
std::vector<VkPipelineExecutableStatisticKHR> shader_stats =
472+
get_shader_executable_stats(pipeline, 0u);
473+
std::cout << "Found " << shader_stats.size() << " Statistics" << std::endl;
474+
if (shader_stats.size() > 0) {
475+
std::cout << "====== Statistics: ======" << std::endl;
476+
std::cout << shader_stats << std::endl;
477+
}
478+
}
479+
480+
#endif // VK_KHR_pipeline_executable_properties
481+
482+
#endif // VULKAN_DEBUG
483+
264484
} // namespace api
265485
} // namespace vkcompute

backends/vulkan/runtime/api/Context.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,36 @@ class Context final {
228228
const bool final_use = false);
229229

230230
void flush();
231+
232+
#ifdef VULKAN_DEBUG
233+
234+
#ifdef VK_KHR_pipeline_executable_properties
235+
236+
VkPipeline get_shader_pipeline(
237+
const vkapi::ShaderInfo& shader,
238+
const vkapi::SpecVarList& spec_constants);
239+
240+
std::vector<VkPipelineExecutablePropertiesKHR> get_pipeline_executable_props(
241+
const VkPipeline pipeline);
242+
243+
std::tuple<
244+
std::vector<VkPipelineExecutableInternalRepresentationKHR>,
245+
std::vector<std::vector<char>>>
246+
get_shader_executable_irs(
247+
const VkPipeline pipeline,
248+
const uint32_t pipeline_exec_idx = 0u);
249+
250+
std::vector<VkPipelineExecutableStatisticKHR> get_shader_executable_stats(
251+
const VkPipeline pipeline,
252+
const uint32_t pipeline_exec_idx = 0u);
253+
254+
void print_shader_executable_properties(
255+
const vkapi::ShaderInfo& shader,
256+
const vkapi::SpecVarList& spec_constants);
257+
258+
#endif // VK_KHR_pipeline_executable_properties
259+
260+
#endif // VULKAN_DEBUG
231261
};
232262

233263
bool available();

backends/vulkan/runtime/vk_api/Adapter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ VkDevice create_logical_device(
8282
#ifdef VK_KHR_shader_float16_int8
8383
VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME,
8484
#endif /* VK_KHR_shader_float16_int8 */
85+
#if defined(VK_KHR_pipeline_executable_properties) && defined(VULKAN_DEBUG)
86+
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME,
87+
#endif /* VK_KHR_pipeline_executable_properties */
8588
};
8689

8790
std::vector<const char*> enabled_device_extensions;

backends/vulkan/runtime/vk_api/Pipeline.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,16 @@ ComputePipeline::ComputePipeline(
287287
&specialization_info, // pSpecializationInfo
288288
};
289289

290+
VkPipelineCreateFlags flags = 0u;
291+
#if defined(VULKAN_DEBUG) && defined(VK_KHR_pipeline_executable_properties)
292+
flags = VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR |
293+
VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR | flags;
294+
#endif /* VULKAN_DEBUG && VK_KHR_pipeline_executable_properties */
295+
290296
const VkComputePipelineCreateInfo compute_pipeline_create_info{
291297
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
292298
nullptr, // pNext
293-
0u, // flags
299+
flags, // flags
294300
shader_stage_create_info, // stage
295301
descriptor.pipeline_layout, // layout
296302
VK_NULL_HANDLE, // basePipelineHandle

backends/vulkan/test/vulkan_compute_api_test.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ TEST_F(VulkanComputeAPITest, print_adapter) {
101101
std::cout << *(context()->adapter_ptr()) << std::endl;
102102
}
103103

104+
#if defined(VULKAN_DEBUG) && defined(VK_KHR_pipeline_executable_properties)
105+
106+
TEST_F(VulkanComputeAPITest, print_shader_executable_properties) {
107+
context()->print_shader_executable_properties(
108+
VK_KERNEL(binary_add_nobroadcast__test_half), {0});
109+
}
110+
111+
#endif // VULKAN_DEBUG && VK_KHR_pipeline_executable_properties
112+
104113
std::vector<int64_t> get_reference_strides(
105114
const std::vector<int64_t>& sizes,
106115
const utils::GPUMemoryLayout layout,

0 commit comments

Comments
 (0)