Then started discussion in llvm discord with @fabianmc . Thanks to him , I have advanced a lot. But still couldn’t make it work. There you will find all the commands in chronological order that I have tried to make it work. I donot want to share it here, because it will take too long space.
But here I am going to share the final pieces that I have tried according to @fabianmc
bash: ./gpubin: cannot execute binary file: Exec format error
The last response I’ve got from @fabianmc in discord is
the code you get here is not PTX, but rather llvm IR with the GPU module embedded as a string.
Now questions are
What am I missing in command pipeline? How can I make it work? Help much needed
Is there any official doc/tutorial? @herhutproposed an official doc for this years ago. . If I can find the way to properly organize the compilation pipeline, I am happy to write that doc as a contribution .
Advanced sorry for asking this very very noob question. I am using llvm-17.0.6. But got the idea from @mehdi_amini that main branch have all the latest cuda development for MLIR. But I am confused, the last commit in main branch is part of llvm-init-18? Or it is the latest for llvm-17? Logically it should be part of llvm 18. The reason for asking is to have a stable build, so that if I update it, the code doesn’t break.
I’m a bit confused here: you’re only passing a gpu.ptx input to nvcc but there is no host code here, this can’t possibly generate a binary that you can run on the host, what am I missing?
The main branch is the current development branch for LLVM 18.
LLVM 17 is almost 5 months old now, so you’re missing on the last 5 months of developments in this area. It’s not much but at the same time many “solution” we may provide here won’t apply!
Like @mehdi_amini said, you need some form of host code to actually launch any kernels on the device. However, if you just want to call some arbitrary GPU function you could link your created binary in with some other kernel. e.g.
clang++ -x cuda foo.cpp --offload-arch=native --offload-new-driver -fgpu-rdc -Xoffload-linker gpu.ptx
I’m assuming this is something close to what you’re asking for. If you’re talking about executing an NVIDIA GPU binary directly, I actually have some infrastructure for that in the libc project that simply executes a main function inside of a GPU executable. I use that to run the test suite.
@jhuber6 Here in the command, you have passed foo.cpp with clang++. But I don’t have any .cpp file to compile. I just want to compile .mlir.
@mehdi_amini & @jhuber6 I had the similar doubt about the host code. For your convenience, I am sharing the .mlir code here. I thought the @main() here is the host code. Because it is calling the kernel.
I have got this following warning telling me, clang++ doesn’t understand the flag --cuda-gpu-arch=sm_86. But its very important for me to generate binary for particular GPU arch.
clang++: warning: argument unused during compilation: '--cuda-gpu-arch=sm_86' [-Wunused-command-line-argument]
warning: overriding the module target triple with x86_64-unknown-linux-gnu [-Woverride-module]
1 warning generated.
I was also trying to chain all the commands using pipe | Like following. But couldn’t do it. It was giving me error messages
./installation/bin/mlir-opt mlir/test/Integration/GPU/CUDA/printf.mlir | ./installation/bin/mlir-opt -test-lower-to-nvvm -o print-cubin.mlir
# Error Message
Translations to perform option: must be specified at least once!
Translations to perform option: must be specified at least once!
Translations to perform option: must be specified at least once!
.....
I fixed the pipeline in my message above. You need to pass cubin-chip=sm_86 to test-lower-to-nvvm pipeline (no need for clang) as it actually compiles the gpu side of the code.
But it is working without the opt-level=3. So any clue, where I can pass the opt-level=3? Or is it because my build is llvm 17.0.6. And those pass options are defined in last updates in main branch (i.e. for llvm-18)?
And If I use only cubin-chip=sm_86, then at clang++ compilation step, it’s still giving me
warning: overriding the module target triple with x86_64-unknown-linux-gnu [-Woverride-module]
1 warning generated.
All up to date features are not in llvm/17.x. In particular opt-level is not there.
Actually, most of new developments on GPU compilation are not there.
Finally I am compiling the exe.ll file with clang++ which actually generates the module target triple x86_64-unknown-linux-gnu warning. [Doesn’t need to point the libs in linker path $LD_LIBRARY_PATH]
So, the 3rd step is overriding the module target triple. What does it even mean? As far as I know about the target triple
Target triple refers to a string in LLVM IR, that describes the target architecture, vendor, and operating system for which a program or a compiler is being built.
Then I have searched inside the cuda binary with both sm_86 and x86_64-unknown-linux-gnu strings using following command. sm_86 is found, but the other one is not found.
hexdump -C exe | grep -i 'sm_86'
# Result
# 00002d30 2e 31 0a 2e 74 61 72 67 65 74 20 73 6d 5f 38 36 |.1..target sm_86|
That warning happens because mlir-translate is not setting the target triple, so when clang compiles exe.ll it sets the target triple to the native one (effectively overriding the triple).
One more thing, exe.ll is not a module with GPU code, instead it is a host module with a string containing the already compiled cubin.