Skip to content

Commit 680965c

Browse files
authored
SPIR-V Runner: Integrate argument parsing library (#2759)
This PR integrates LLVM based argument parsing library into SPIR-V Runner and closes #2568 ``` /intel-xpu-backend-for-triton/utils/SPIRVRunner$ ./build/SPIRVRunner -o tensor_2 Running on device: Intel(R) Data Center GPU Max 1100 Read 3772 byte kernel. Loaded kernel with 0 registers and 0 register spills. Tensor output: [98432], Float (393728 bytes) Output Tensor Path: intel-xpu-backend-for-triton/utils/SPIRVRunner/cpp_outs.pt intel-xpu-backend-for-triton/utils/SPIRVRunner$ ./build/SPIRVRunner -o tensor_2 -p Running on device: Intel(R) Data Center GPU Max 1100 Read 3772 byte kernel. Loaded kernel with 0 registers and 0 register spills. Tensor output: [98432], Float (393728 bytes) Kernel execution time: 0.0096 ms Output Tensor Path: intel-xpu-backend-for-triton/utils/SPIRVRunner/cpp_outs.pt intel-xpu-backend-for-triton/utils/SPIRVRunner$ ./build/SPIRVRunner --help USAGE: SPIRVRunner [options] OPTIONS: Color Options: --color - Use colors in output (default=autodetect) General options: -o <filename> - Specify Output Tensor Name -p - Enable Profiling ```
1 parent f6f26c2 commit 680965c

File tree

5 files changed

+82
-44
lines changed

5 files changed

+82
-44
lines changed

utils/SPIRVRunner/CMakeLists.txt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ list(APPEND CMAKE_PREFIX_PATH "${ONEAPI_ROOT}/tbb/latest/lib/cmake/tbb/")
1616

1717
find_package(Torch REQUIRED)
1818

19+
# Include LLVM Support Library for CLI parsing
20+
find_package(LLVM REQUIRED CONFIG)
21+
include_directories(${LLVM_INCLUDE_DIRS})
22+
add_definitions(${LLVM_DEFINITIONS})
23+
add_library(llvm_parser OBJECT llvm_parser.cpp)
24+
target_compile_options(llvm_parser PRIVATE -fno-rtti)
25+
1926
include(ExternalProject)
2027
ExternalProject_Add(
2128
json
@@ -34,14 +41,13 @@ set(COMPILE_FLAGS "-fsycl -Wall -fpreview-breaking-changes")
3441
set(LINK_FLAGS "-fsycl -lze_loader")
3542

3643
set(SYCL_FUNCTIONS_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/intel/backend/include")
37-
3844
set(TARGET_NAME SPIRVRunner)
39-
add_executable(${TARGET_NAME} ${TARGET_NAME}.cpp)
45+
add_executable(${TARGET_NAME} ${TARGET_NAME}.cpp $<TARGET_OBJECTS:llvm_parser>)
4046
target_include_directories(${TARGET_NAME} PRIVATE
41-
"${ONEAPI_ROOT}/compiler/latest/include" ${SYCL_FUNCTIONS_INCLUDE_DIR} ${JSON_INCLUDE_DIR})
47+
"${ONEAPI_ROOT}/compiler/latest/include" ${SYCL_FUNCTIONS_INCLUDE_DIR} ${JSON_INCLUDE_DIR})
4248
set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS}")
4349
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "${LINK_FLAGS}")
4450
add_dependencies(${TARGET_NAME} json)
45-
46-
target_link_libraries(${TARGET_NAME} "${TORCH_LIBRARIES}")
51+
llvm_map_components_to_libnames(LLVM_LIBS Support)
52+
target_link_libraries(${TARGET_NAME} PRIVATE "${TORCH_LIBRARIES}" "${LLVM_LIBS}")
4753
set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD 17)

utils/SPIRVRunner/README.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@ find .venv -name TorchConfig.cmake
1010
```
1111
in the top level Triton directory.
1212

13+
`SPIRVRunner` depends on LLVM support libarary for argument parsing in order to use this run following in the top level Triton directory.
14+
```
15+
scripts/compile-triton.sh --llvm
16+
```
17+
18+
SPIR-V Runner build steps:
19+
1320
```
1421
mkdir build
1522
cd build
16-
CMAKE_PREFIX_PATH=/abs/path/to/TorchConfig.cmake/FromAbove/ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
23+
CMAKE_PREFIX_PATH=/abs/path/to/TorchConfig.cmake/FromAbove/ LLVM_DIR=/abs/path/to/packages/llvm cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
1724
make -j
1825
```
1926

@@ -38,7 +45,17 @@ Following input data is generated,
3845
## Running
3946

4047
Help:
41-
`./build/SPIRVRunner` < Output Tensor Name >
48+
49+
```
50+
USAGE: SPIRVRunner [options]
51+
52+
General options:
53+
54+
-o <string> - <Specify Output Tensor Name>
55+
56+
-p - Enable kernel time profiling
57+
```
58+
4259

4360
Note: `Output Tensor Name` is essentially a chosen tensor that needs to be copied back to the CPU and written to disk. Additionally, the name must match the tensor's name (tensor_) and number as specified in the JSON file. Please refer args_data.json file.
4461

@@ -47,18 +64,17 @@ Note: `Output Tensor Name` is essentially a chosen tensor that needs to be copi
4764
`SPIRVRunner` is configured to run the `add_kernel.spv` SPIRV binary with inputs `tensor_0.pt` and `tensor_1.pt` and output `tensor_2.pt`. `add_kernel.spv` was generated from the `01-vector-add.py` tutorial.
4865

4966
SPIRVRunner Usage:
50-
`./build/SPIRVRunner tensor_2`
67+
`./build/SPIRVRunner -o tensor_2 -p`
5168

5269
Expected output follows:
5370

5471
```
5572
Running on device: Intel(R) Data Center GPU Max 1100
5673
Read 3772 byte kernel.
57-
create kernel:add_kernel
5874
Loaded kernel with 0 registers and 0 register spills.
5975
Tensor output: [98432], Float (393728 bytes)
60-
Kernel return output: 1.37129
61-
[ CPUFloatType{} ]
76+
Kernel execution time: 0.0096 ms
77+
Output Tensor Path: /abs/path/utils/SPIRVRunner/cpp_outs.pt
6278
```
6379

6480
The GPU hardware, shape and data type of each Tensor (along with number of bytes), and kernel information are printed. The shape and data type of the output Tensor is currently printed, along with the the first cell in the output. Ensuring the value of the first cell is non-zero allows for a quick sanity check. The output Tensor is written to a file `cpp_outs.pt` which is a Tensor in PyTorch format. Typically, we will create a quick Python script to read the input Tensor, run the same computations in PyTorch, and then compare the PyTorch result with the loaded `cpp_outs.pt` Tensor using the PyTorch testing API.

utils/SPIRVRunner/SPIRVRunner.cpp

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@
22
#include <sycl/sycl.hpp>
33
#include <torch/torch.h>
44

5+
#include "llvm_parser.h"
6+
#include "sycl_functions.h"
57
#include <algorithm>
68
#include <cstdlib>
79
#include <filesystem>
810
#include <fstream>
911
#include <ios>
1012
#include <iostream>
13+
#include <nlohmann/json.hpp>
1114
#include <regex>
1215
#include <string>
1316
#include <vector>
14-
15-
#include "sycl_functions.h"
16-
#include <nlohmann/json.hpp>
17-
1817
using json = nlohmann::json;
1918
using ordered_json = nlohmann::ordered_json;
2019

@@ -411,38 +410,14 @@ at::Tensor launchKernel(sycl::queue stream, sycl::kernel kernel,
411410
return triton_args.host_outbuffer;
412411
}
413412

414-
bool check_option_amoung_argv(int argc, char **argv, std::string option) {
415-
bool res = false;
416-
if (argc > 2) {
417-
// optional parameters can be in any order
418-
for (int i = 2; i < argc; i++) {
419-
if (argv[i] == option) {
420-
res = true;
421-
break;
422-
}
423-
}
424-
}
425-
return res;
426-
}
427-
428413
int main(int argc, char **argv) {
429414
try {
430-
std::string enable_profiling = "--enable-profiling";
431-
if (argc < 2) {
432-
std::cout << "Help: " << std::endl;
433-
std::cout << "<Executable> <Output Tensor Name>" << std::endl;
434-
std::cout << "./build/SPIRVRunner tensor_2" << std::endl;
435-
std::cout << "To get kernel time, use:" << std::endl;
436-
std::cout << "./build/SPIRVRunner tensor_2 " << enable_profiling
437-
<< std::endl;
438-
throw std::runtime_error("Input arguments are missing \n");
439-
}
415+
command_line_parser cli(argc, argv);
416+
auto cliopts = cli.parse();
440417

441418
// initialize sycl runtime
442-
bool get_kernel_time =
443-
check_option_amoung_argv(argc, argv, enable_profiling);
444419
sycl::queue q;
445-
if (get_kernel_time) {
420+
if (cliopts.get_kernel_time) {
446421
sycl::property_list prop_list{sycl::property::queue::enable_profiling()};
447422
q = sycl::queue(sycl::gpu_selector_v, exception_handler, prop_list);
448423
} else {
@@ -455,7 +430,7 @@ int main(int argc, char **argv) {
455430
initDevices(&q);
456431

457432
// Parse the JSON file and create argument dictionary
458-
KernelArguments tritonArgDict(argv[1]);
433+
KernelArguments tritonArgDict(cliopts.output_tensor);
459434

460435
// read spirv
461436
auto spirv = read_spirv(tritonArgDict.spv_name);
@@ -469,7 +444,8 @@ int main(int argc, char **argv) {
469444
std::cout << "Loaded kernel with " << n_regs << " registers and "
470445
<< n_spills << " register spills." << std::endl;
471446

472-
auto output = launchKernel(q, kernel, tritonArgDict, get_kernel_time);
447+
auto output =
448+
launchKernel(q, kernel, tritonArgDict, cliopts.get_kernel_time);
473449

474450
auto output_tensor = tritonArgDict.spirv_dump_dir + "/cpp_outs.pt";
475451
write_tensor(output_tensor, output);

utils/SPIRVRunner/llvm_parser.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "llvm_parser.h"
2+
3+
command_line_parser::command_line_parser(int argc, char **argv)
4+
: argc(argc), argv(argv) {}
5+
6+
command_line_parser::options command_line_parser::parse() {
7+
options opts;
8+
llvm::cl::opt<std::string> output_tensor(
9+
"o", llvm::cl::desc("<Specify Output Tensor Name>"), llvm::cl::Required);
10+
llvm::cl::opt<bool> enable_profiling(
11+
"p", llvm::cl::desc("Enable kernel time profiling"),
12+
llvm::cl::init(opts.get_kernel_time));
13+
14+
llvm::cl::ParseCommandLineOptions(argc, argv, "SPIRVRunner\n");
15+
16+
opts.output_tensor = output_tensor;
17+
opts.get_kernel_time = enable_profiling;
18+
19+
return opts;
20+
}

utils/SPIRVRunner/llvm_parser.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef LLVM_PARSER_H
2+
#define LLVM_PARSER_H
3+
4+
#include "llvm/Support/CommandLine.h"
5+
6+
class command_line_parser {
7+
public:
8+
struct options {
9+
std::string output_tensor;
10+
bool get_kernel_time = false;
11+
};
12+
13+
command_line_parser(int argc, char **argv);
14+
options parse();
15+
16+
private:
17+
int argc;
18+
char **argv;
19+
};
20+
#endif

0 commit comments

Comments
 (0)