我编写了以下CUDA内核,并尝试将其加载到模块中:
#include <stdio.h>
extern "C" // ensure function name to be exactly "vadd"
{
__global__ void vadd(const float *a, const float *b, float *c)
{
int i = threadIdx.x + blockIdx.x * blockDim.x;
printf("Thread id %d\n", i);
c[i] = a[i] + b[i];
}
}
我使用以下命令将其编译为ptx代码:
nvcc -ptx -arch=sm_20 vadd.cu
尝试使用cuModuleLoad
将此文件加载到模块时,出现CUDA 200错误(内核映像无效)。如何找出内核映像有什么问题?我试过了ptxas
,但根据这个,生成的ptx代码很好。
编辑:这是我用来加载模块的代码:
#include "cuda.h"
#include <cassert>
#include <dlfcn.h>
#include <stdio.h>
void check(CUresult err) {
if (err != CUDA_SUCCESS) {
printf("Error %i\n", err);
}
assert(err == CUDA_SUCCESS);
}
int main(int argc, char **argv) {
void *cuda = dlopen("libcuda.so", RTLD_NOW | RTLD_DEEPBIND | RTLD_GLOBAL);
assert(cuda != NULL);
printf("cuInit\n");
CUresult (*Init)() = (CUresult (*)()) dlsym(cuda, "cuInit");
check(Init());
printf("cuDeviceGet\n");
CUresult (*DeviceGet)(CUdevice *, int) = (CUresult (*)(CUdevice *, int)) dlsym(cuda, "cuDeviceGet");
CUdevice device;
check(DeviceGet(&device, 0));
printf("cuCtxCreate\n");
CUresult (*CtxCreate)(CUcontext * , unsigned int, CUdevice) = (CUresult (*)(CUcontext * , unsigned int, CUdevice)) dlsym(cuda, "cuCtxCreate");
CUcontext context;
check(CtxCreate(&context, 0, device));
printf("cuModuleLoad\n");
CUresult (*ModuleLoad)(CUmodule *, const char*) = (CUresult (*)(CUmodule *, const char*)) dlsym(cuda, "cuModuleLoad");
CUmodule mod;
check(ModuleLoad(&mod, "vadd.ptx"));
return 0;
}
答案 0 :(得分:2)
这与Why cuCtxCreate creates old context?有关:您直接使用cuCtxCreate
,这会为您提供与您printf
的使用不兼容的旧API上下文(v3.1)。您可以使用cuCtxGetApiVersion
检查API版本。如果您切换到cuCtxCreate_v2
(通常在#define
中的某些cuda.h
使用的LD_DEBUG=symbols
),您将获得更新的API背景。
为了发现这种差异,我使用cuCtxCreate
运行您的示例,并将其与直接使用CUDA API进行比较(因为它正确运行您的示例PTX)。比较符号分辨率,最大的区别是对cuCtxCreate(...)
symbol=cuCtxCreate_v2; lookup in file=./test [0]
symbol=cuCtxCreate_v2; lookup in file=/usr/lib/x86_64-linux-gnu/libcuda.so.1 [0]
的调用:
dlsym(..., "cuCtxCreate")
...在原始代码中,使用cuCtxCreate
直接映射到{{1}}。