1

我正在尝试将一些 C 代码移植到 cuda 内核。我移植的代码普遍使用省略号。当我尝试在如下所示的设备函数中使用省略号时,我收到一条错误消息,指出设备函数中不允许使用省略号。

__device__ int add(int a, ...){}

但是,cuda 支持在主机和设备函数中使用 printf,并在自己的代码中使用省略号,如下 common_functions.h 中所示。

extern "C"
{
extern _CRTIMP __host__ __device__ __device_builtin__ __cudart_builtin__ int     __cdecl printf(const char*, ...);
extern _CRTIMP __host__ __device__ __device_builtin__ __cudart_builtin__ int     __cdecl fprintf(FILE*, const char*, ...);
extern _CRTIMP __host__ __device__ __cudart_builtin__ void*   __cdecl malloc(size_t) __THROW;
extern _CRTIMP __host__ __device__ __cudart_builtin__ void    __cdecl free(void*) __THROW;

}

有没有办法在设备函数中使用省略号?

我不想硬编码最大数量的参数,然后更改所有调用。
我也不想编写自定义可变参数函数方法。

我还尝试创建一个 PTX 文件,我可以用它来替换省略号的用法,因为 ISA PTX 文档似乎具有处理可变参数的工具(请注意,文档说它不支持它们,然后提供了一个带有支持功能和示例的段落.也许,有一个错字?)。在下面定义的过程中,我一直得到一个简单的 PTX 文件,但在最后一条评论中遇到了可执行问题。我计划阅读 nvcc 编译器文档以尝试理解这一点。

如何从 CUDA C 调用 ptx 函数?

我正在使用 GTX660,我认为它是 Ubuntu 12.04 上的 3.0 级和 cuda 5.0 工具包。

关于下面提到的“魔法”的更新:

在我看来,编译器中一定发生了一些特别的事情来限制省略号的使用并做一些特别的事情。当我如下调用 printf 时:

printf("The result = %i from adding %i numbers.", result, 2);

我很惊讶在 ptx 中发现了这个:

.extern .func  (.param .b32 func_retval0) vprintf
(
.param .b64 vprintf_param_0,
.param .b64 vprintf_param_1
)

然后

    add.u64     %rd2, %SP, 0;
st.u32  [%SP+0], %r5;
mov.u32     %r6, 2;
st.u32  [%SP+4], %r6;
// Callseq Start 1
{
.reg .b32 temp_param_reg;
.param .b64 param0;
st.param.b64    [param0+0], %rd1;
.param .b64 param1;
st.param.b64    [param1+0], %rd2;
.param .b32 retval0;
call.uni (retval0), 
vprintf, 
(
param0, 
param1
);

在我看来,编译器接受 printf 的省略号,但随后交换对 vprintf 的调用并手动动态创建 va_list。va_list 是设备函数中的有效类型。

4

1 回答 1

1

正如@JaredHoberock 所说(我认为如果我创建一个答案,他不会介意):

__device__函数不能有省略号参数;这就是您收到编译器错误消息的原因。

内置printf函数是一种特殊情况,并不表示对省略号的一般支持。

可以提到一些替代方案,但我所知道的没有一个允许真正的通用变量参数支持。例如,正如 Jared 所说,您可以简单地定义一些参数,其中一些/大部分都指定了默认值,因此不需要显式传递它们。

您也可以像在cuPrintf 示例代码中所做的那样使用模板玩游戏来尝试模拟变量参数,但这也不会是任意可扩展的,我不认为。

于 2014-02-26T15:06:19.103 回答