gpt4 book ai didi

cuda - 在 CUDA NVRTC 代码中包含 C 标准头文件

转载 作者:行者123 更新时间:2023-12-03 17:15:12 27 4
gpt4 key购买 nike

我正在编写一个在运行时使用 NVRTC(CUDA 9.2 版和 NVRTC 7.5 版)编译的 CUDA 内核,它需要 stdint.h标题,以便拥有 int32_t等类型。

如果我编写没有包含的内核源代码,它可以正常工作。例如内核

extern "C" __global__ void f() { ... }

编译为 PTX 代码,其中 f 定义为 .visible .entry f .

但是如果内核源代码是
#include <stdint.h>
extern "C" __global__ void f() { ... }

它报告 A function without execution space annotations (__host__/__device__/__global__) is considered a host function, and host functions are not allowed in JIT mode. (也没有 extern "C" )。

路过 -default-device制作PTX代码 .visible .func f ,因此无法从主机调用该函数。

有没有办法在源代码中包含头文件,并且仍然有 __global__入口函数?或者,一种知道 NVRTC 编译器使用哪种整数大小约定的方法,以便 int32_t等类型可以手动定义?

编辑:
显示问题的示例程序:
#include <cstdlib>
#include <string>
#include <vector>
#include <memory>
#include <cassert>
#include <iostream>

#include <cuda.h>
#include <cuda_runtime.h>
#include <nvrtc.h>

[[noreturn]] void fail(const std::string& msg, int code) {
std::cerr << "error: " << msg << " (" << code << ')' << std::endl;
std::exit(EXIT_FAILURE);
}


std::unique_ptr<char[]> compile_to_ptx(const char* program_source) {
nvrtcResult rv;

// create nvrtc program
nvrtcProgram prog;
rv = nvrtcCreateProgram(
&prog,
program_source,
"program.cu",
0,
nullptr,
nullptr
);
if(rv != NVRTC_SUCCESS) fail("nvrtcCreateProgram", rv);

// compile nvrtc program
std::vector<const char*> options = {
"--gpu-architecture=compute_30"
};
//options.push_back("-default-device");
rv = nvrtcCompileProgram(prog, options.size(), options.data());
if(rv != NVRTC_SUCCESS) {
std::size_t log_size;
rv = nvrtcGetProgramLogSize(prog, &log_size);
if(rv != NVRTC_SUCCESS) fail("nvrtcGetProgramLogSize", rv);

auto log = std::make_unique<char[]>(log_size);
rv = nvrtcGetProgramLog(prog, log.get());
if(rv != NVRTC_SUCCESS) fail("nvrtcGetProgramLog", rv);
assert(log[log_size - 1] == '\0');

std::cerr << "Compile error; log:\n" << log.get() << std::endl;

fail("nvrtcCompileProgram", rv);
}

// get ptx code
std::size_t ptx_size;
rv = nvrtcGetPTXSize(prog, &ptx_size);
if(rv != NVRTC_SUCCESS) fail("nvrtcGetPTXSize", rv);

auto ptx = std::make_unique<char[]>(ptx_size);
rv = nvrtcGetPTX(prog, ptx.get());
if(rv != NVRTC_SUCCESS) fail("nvrtcGetPTX", rv);
assert(ptx[ptx_size - 1] == '\0');

nvrtcDestroyProgram(&prog);

return ptx;
}

const char program_source[] = R"%%%(
//#include <stdint.h>
extern "C" __global__ void f(int* in, int* out) {
out[threadIdx.x] = in[threadIdx.x];
}
)%%%";

int main() {
CUresult rv;

// initialize CUDA
rv = cuInit(0);
if(rv != CUDA_SUCCESS) fail("cuInit", rv);

// compile program to ptx
auto ptx = compile_to_ptx(program_source);
std::cout << "PTX code:\n" << ptx.get() << std::endl;
}

//#include <stdint.h>在内核源代码中取消注释它不再编译。当 //options.push_back("-default-device");未注释它编译但不标记函数 f.entry .

CMakeLists.txt 编译它(需要 CUDA 驱动程序 API + NVRTC)
cmake_minimum_required(VERSION 3.4)
project(cudabug CXX)

find_package(CUDA REQUIRED)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED 14)

add_executable(cudabug cudabug.cc)
include_directories(SYSTEM ${CUDA_INCLUDE_DIRS})
link_directories(${CUDA_LIBRARY_DIRS})
target_link_libraries(cudabug PUBLIC ${CUDA_LIBRARIES} nvrtc cuda)

最佳答案

[前言:这是一个非常笨拙的答案,并且特定于 GNU 工具链(尽管我怀疑问题中的问题也特定于 GNU 工具链)]。

看起来这里的问题是 GNU 标准头文件 features.h被拉入 stdint.h并且最终定义了许多具有默认值 __host__ 的 stub 函数编译空间并导致 nvrtc 炸毁。似乎还有-default-device选项将导致解析 glibC 编译器功能集,这会使整个 nvrtc 编译器失败。

您可以通过为标准库预定义一个排除所有主机功能的功能集来解决这个问题(以一种非常hacky 的方式)。将 JIT 内核代码更改为

const char program_source[] = R"%%%(
#define __ASSEMBLER__
#define __extension__
#include <stdint.h>
extern "C" __global__ void f(int32_t* in, int32_t* out) {
out[threadIdx.x] = in[threadIdx.x];
}
)%%%";

给我这个:
$ nvcc -std=c++14 -ccbin=g++-7 jit_header.cu -o jitheader -lnvrtc -lcuda
$ ./jitheader
PTX code:
//
// Generated by NVIDIA NVVM Compiler
//
// Compiler Build ID: CL-24330188
// Cuda compilation tools, release 9.2, V9.2.148
// Based on LLVM 3.4svn
//

.version 6.2
.target sm_30
.address_size 64

// .globl f

.visible .entry f(
.param .u64 f_param_0,
.param .u64 f_param_1
)
{
.reg .b32 %r<3>;
.reg .b64 %rd<8>;


ld.param.u64 %rd1, [f_param_0];
ld.param.u64 %rd2, [f_param_1];
cvta.to.global.u64 %rd3, %rd2;
cvta.to.global.u64 %rd4, %rd1;
mov.u32 %r1, %tid.x;
mul.wide.u32 %rd5, %r1, 4;
add.s64 %rd6, %rd4, %rd5;
ld.global.u32 %r2, [%rd6];
add.s64 %rd7, %rd3, %rd5;
st.global.u32 [%rd7], %r2;
ret;
}

大警告:这适用于我尝试过的 glibC 系统。它可能不适用于其他工具链或 libC 实现(如果他们确实有这个问题)。

关于cuda - 在 CUDA NVRTC 代码中包含 C 标准头文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50565200/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com