我需要在内核函数中动态地分配一些数组。我该怎么做呢?
我的代码是这样的:
__global__ func(float *grid_d,int n, int nn){
int i,j;
float x[n],y[nn];
//Do some really cool and heavy computations here that takes hours.
}
字符串
但这不会工作。如果这是在主机代码中,我可以使用malloc。cudaMalloc需要一个指针在主机上,另一个在设备上。在内核函数中,我没有主机指针。
那我该怎么办
如果分配所有数组需要很长时间(几秒钟)(我需要4个大小为n的数组和5个大小为nn的数组),这不会是一个问题,因为内核可能至少运行20分钟。
5条答案
按热度按时间wecizke31#
动态内存分配仅在compute capability 2.x和更新的硬件上受支持。您可以在内核中使用C++ new关键字或malloc,因此您的示例可以变为:
字符串
这会在一个本地内存运行时堆上分配内存,该内存具有上下文的生命周期,因此如果您不打算再次使用内存,请确保在内核运行结束后释放内存。您还应该注意,运行时堆内存不能直接从主机API访问,因此您不能将内核内部分配的指针作为参数传递给
cudaMemcpy
。bwleehnv2#
@talonmies回答了你关于如何在内核中动态分配内存的问题。这是一个补充答案,解决了
__device__ malloc()
的性能问题,也是你可能想考虑的替代方案。在内核中动态分配内存可能很诱人,因为它允许GPU代码看起来更像CPU代码。但它可能会严重影响性能。我写了一个自包含的测试,并在下面包含它。测试启动了大约260万个线程。每个线程使用从线程索引派生的一些值填充16个整数的全局内存,然后将这些值相加并返回总和。
测试实现了两种方法,第一种方法使用
__device__ malloc()
,第二种方法使用在内核运行之前分配的内存。在我的2.0设备上,使用
__device__ malloc()
时,内核运行时间为1500 ms,使用预分配内存时为27 ms。换句话说,在内核内动态分配内存时,测试运行时间延长56倍。时间包括外部循环cudaMalloc()
/cudaFree()
,这不是内核的一部分。如果使用相同数量的线程多次启动同一个内核,通常情况下,cudaMalloc()
/cudaFree()
的成本是在所有内核启动时分摊的。这使得差异更大,大约为60倍。推测,我认为性能下降部分是由隐式序列化引起的。GPU可能必须序列化所有对
__device__ malloc()
的并发调用,以便为每个调用者提供单独的内存块。不使用
__device__ malloc()
的版本在运行内核之前分配所有GPU内存。内存指针被传递给内核。每个线程计算到先前分配的内存中的索引,而不是使用__device__ malloc()
。预先分配内存的潜在问题是,如果只有一些线程需要分配内存,并且不知道这些线程是哪些线程,则需要为所有线程分配内存。如果没有足够的内存,减少每个内核调用的线程数可能比使用
__device__ malloc()
更有效。__device__ malloc()
正在后台运行,并且会看到类似的性能下降。测试
__device__ malloc()
的性能:字符串
输出量:
型
piok6c0g3#
如果n和nn的值在内核被调用之前就已经知道了,那么为什么不在主机端cudaMalloc内存并将设备内存指针传递给内核呢?
u0njafvf4#
根据@rogerdahl的帖子中的概念运行了一个实验。假设:
在GPU本地的malloc+free调用似乎比
cudaMalloc
+cudaFree
调用快得多。程序的输出:字符串
我省略了
timer.h
和timer.cpp
的代码,但下面是测试本身的代码:型
如果你发现了错误,请在评论中注明,我会尽力修复它们。
我又用更大的东西做了一遍:
型
cudaMalloc还是慢了很多:
型
jjjwad0x5#
也许你应该测试一下
字符串
相反
型