C++ 结构中的CUDA设备函数指针没有静态指针或符号副本
如果可能的话,我的计划流程如下所示:C++ 结构中的CUDA设备函数指针没有静态指针或符号副本,c++,cuda,gpu,C++,Cuda,Gpu,如果可能的话,我的计划流程如下所示: typedef struct structure_t { [...] /* device function pointer. */ __device__ float (*function_pointer)(float, float, float[]); [...] } structure; [...] /* function to be assigned. */ __device__ float my_function (float a,
typedef struct structure_t
{
[...]
/* device function pointer. */
__device__ float (*function_pointer)(float, float, float[]);
[...]
} structure;
[...]
/* function to be assigned. */
__device__ float
my_function (float a, float b, float c[])
{
/* do some stuff on the device. */
[...]
}
void
some_structure_initialization_function (structure *st)
{
/* assign. */
st->function_pointer = my_function;
[...]
}
这是不可能的,并且在编译过程中,由于在结构中放置_device _uu而导致了一个常见的错误
error: attribute "device" does not apply here
error: attribute "device" does not apply here
这里有一些关于stackoverflow的类似问题的例子,但它们都涉及在结构外部使用静态指针。例如和。我以前在其他代码中也采用了类似的方法,在这些代码中,我很容易使用静态设备指针,并在任何结构之外定义它们。目前,这是一个问题。它是作为某种API编写的,用户可以定义一个、两个或几十个需要包含设备函数指针的结构。因此,在结构外部定义静态设备指针是一个主要问题
我相当肯定,通过使用符号副本,我在上面链接的帖子中找到了答案,但我无法成功地使用它们。您试图做的是可能的,但是您在声明和定义将保存和使用函数指针的结构时犯了一些错误
这是不可能的,并在编译过程中以一个熟悉的错误结束
关于在结构中放置_装置_
error: attribute "device" does not apply here
error: attribute "device" does not apply here
这只是因为您试图将内存空间分配给结构或类数据成员,这在CUDA中是非法的。定义或实例化类时,隐式设置所有类或结构数据成员的内存空间。所以有些东西只是略微不同(而且更具体):
您将得到一个完全可编译且可运行的示例。这里有两个\uuuuuuu设备
函数和一个静态函数表,为主机代码在运行时检索\uuuu设备
函数指针提供了一种机制。每个\uuuu device\uuuu
函数调用内核一次,并显示结果,以及从主机代码实例化和调用的完全相同的functor和函数(因此在主机上运行)以进行比较:
$ nvcc -arch=sm_30 -Xptxas="-v" -o function_pointer function_pointer.cu
ptxas info : Compiling entry function '_Z6kernelffPFfff6float4EPKS_Pfi' for 'sm_30'
ptxas info : Function properties for _Z6kernelffPFfff6float4EPKS_Pfi
16 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Function properties for _Z2f1ff6float4
24 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Function properties for _Z2f2ff6float4
24 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 16 registers, 356 bytes cmem[0], 16 bytes cmem[3]
$ ./function_pointer
0 1 2 ( 0, 1, 2, 3 ) 13 13 9 9
1 1 2 ( 4, 5, 6, 7 ) 45 45 25 25
2 1 2 ( 8, 9, 10, 11 ) 77 77 41 41
3 1 2 ( 12, 13, 14, 15 ) 109 109 57 57
4 1 2 ( 16, 17, 18, 19 ) 141 141 73 73
5 1 2 ( 20, 21, 22, 23 ) 173 173 89 89
6 1 2 ( 24, 25, 26, 27 ) 205 205 105 105
7 1 2 ( 28, 29, 30, 31 ) 237 237 121 121
8 1 2 ( 32, 33, 34, 35 ) 269 269 137 137
9 1 2 ( 36, 37, 38, 39 ) 301 301 153 153
10 1 2 ( 40, 41, 42, 43 ) 333 333 169 169
11 1 2 ( 44, 45, 46, 47 ) 365 365 185 185
12 1 2 ( 48, 49, 50, 51 ) 397 397 201 201
13 1 2 ( 52, 53, 54, 55 ) 429 429 217 217
14 1 2 ( 56, 57, 58, 59 ) 461 461 233 233
15 1 2 ( 60, 61, 62, 63 ) 493 493 249 249
16 1 2 ( 64, 65, 66, 67 ) 525 525 265 265
17 1 2 ( 68, 69, 70, 71 ) 557 557 281 281
18 1 2 ( 72, 73, 74, 75 ) 589 589 297 297
19 1 2 ( 76, 77, 78, 79 ) 621 621 313 313
如果我正确理解了您的问题,那么上面的示例将为您提供在设备代码中实现您的想法所需的几乎所有设计模式。您尝试的是可能的,但是,在声明和定义将保存和使用函数指针的结构时,您犯了一些错误
这是不可能的,并在编译过程中以一个熟悉的错误结束
关于在结构中放置_装置_
error: attribute "device" does not apply here
error: attribute "device" does not apply here
这只是因为您试图将内存空间分配给结构或类数据成员,这在CUDA中是非法的。定义或实例化类时,隐式设置所有类或结构数据成员的内存空间。所以有些东西只是略微不同(而且更具体):
您将得到一个完全可编译且可运行的示例。这里有两个\uuuuuuu设备
函数和一个静态函数表,为主机代码在运行时检索\uuuu设备
函数指针提供了一种机制。每个\uuuu device\uuuu
函数调用内核一次,并显示结果,以及从主机代码实例化和调用的完全相同的functor和函数(因此在主机上运行)以进行比较:
$ nvcc -arch=sm_30 -Xptxas="-v" -o function_pointer function_pointer.cu
ptxas info : Compiling entry function '_Z6kernelffPFfff6float4EPKS_Pfi' for 'sm_30'
ptxas info : Function properties for _Z6kernelffPFfff6float4EPKS_Pfi
16 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Function properties for _Z2f1ff6float4
24 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Function properties for _Z2f2ff6float4
24 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 16 registers, 356 bytes cmem[0], 16 bytes cmem[3]
$ ./function_pointer
0 1 2 ( 0, 1, 2, 3 ) 13 13 9 9
1 1 2 ( 4, 5, 6, 7 ) 45 45 25 25
2 1 2 ( 8, 9, 10, 11 ) 77 77 41 41
3 1 2 ( 12, 13, 14, 15 ) 109 109 57 57
4 1 2 ( 16, 17, 18, 19 ) 141 141 73 73
5 1 2 ( 20, 21, 22, 23 ) 173 173 89 89
6 1 2 ( 24, 25, 26, 27 ) 205 205 105 105
7 1 2 ( 28, 29, 30, 31 ) 237 237 121 121
8 1 2 ( 32, 33, 34, 35 ) 269 269 137 137
9 1 2 ( 36, 37, 38, 39 ) 301 301 153 153
10 1 2 ( 40, 41, 42, 43 ) 333 333 169 169
11 1 2 ( 44, 45, 46, 47 ) 365 365 185 185
12 1 2 ( 48, 49, 50, 51 ) 397 397 201 201
13 1 2 ( 52, 53, 54, 55 ) 429 429 217 217
14 1 2 ( 56, 57, 58, 59 ) 461 461 233 233
15 1 2 ( 60, 61, 62, 63 ) 493 493 249 249
16 1 2 ( 64, 65, 66, 67 ) 525 525 265 265
17 1 2 ( 68, 69, 70, 71 ) 557 557 281 281
18 1 2 ( 72, 73, 74, 75 ) 589 589 297 297
19 1 2 ( 76, 77, 78, 79 ) 621 621 313 313
如果我正确理解了您的问题,上面的示例将为您提供在设备代码中实现您的想法所需的几乎所有设计模式。非常感谢您的详细回答。这给了我在代码中实现想法所需的一切。已经开始运行了。我会接受这个答案。为什么你删除了C标签?因为这是一个C++问题。尽管被标记为“CUDA C”,但是设备语言实际上是C++的子集。主机和设备代码都是用C++编译器编译的,结构、指针和函数的语义遵循C++惯例。这很好,但是我的代码完全是C,而且我的问题中没有C++。我想,如果说它应该同时具备这两个方面的话,那么它的基本原理是相当直截了当的。你看一下你问题中的那些结构,看到“普通C”。用于编译它的工具链是C++,并且只包含数据成员的C++结构。您抱怨的语法错误的原因是因为C++语义应用于那些数据成员。当您编写代码并使用CUDA工具链编译时,您正在编写C++代码,不管您是否意识到。非常感谢您的详细答复。这给了我在代码中实现想法所需的一切。已经开始运行了。我会接受这个答案。为什么你删除了C标签?因为这是一个C++问题。尽管被标记为“CUDA C”,但是设备语言实际上是C++的子集。主机和设备代码都是用C++编译器编译的,结构、指针和函数的语义遵循C++惯例。这很好,但是我的代码完全是C,而且我的问题中没有C++。我想,如果说它应该同时具备这两个方面的话,那么它的基本原理是相当直截了当的。你看一下你问题中的那些结构,看到“普通C”。用于编译它的工具链是C++,并且只包含数据成员的C++结构。您抱怨的语法错误的原因是因为C++语义应用于那些数据成员。当您编写代码并使用CUDA工具链编译时,您是否正在编写C++代码,不管您是否意识到。