我现在正在开发一个使用GPU的项目,这使得我的结果比CPU慢。 原因是我将一个太小的数据数组作为输入(长度= 1024)
我想将更多数据排入队列,但由于内存使用情况,我陷入困境。 我在我的内核283函数内部进行计算,每个函数在481个周期内进行计算。
因此,为了取回我的结果,我必须创建一个大小为N(此处为1024)x 481 x 283的双精度数组(因为283函数返回双精度值)
这个长度太大了。由于我想放置更多数据,输出将增加481 x 283,我将达到GPU的内存限制。我不知道如何使用更少的内存。
这是我的内核函数的一个例子:
PERIODS = 481
data =输入get_global_id(0)
OUTPUT(get_global_id(0),t,x)是存储结果的存取器(三维数组)
for(int t = 0; t< PERIODS; t ++)
OUTPUT(get_global_id(0),t,1)= function1(data,t);
for(int t = 0; t< PERIODS; t ++)
OUTPUT(get_global_id(0),t,2)= function2(data,t);
for(int t = 0; t< PERIODS; t ++)
OUTPUT(get_global_id(0),t,3)= function3(data,t);
当然它看起来很糟糕,但问题是我的“被叫”功能有时需要T = 12或T = 24的值。所以我必须计算每个函数的所有周期,以确保它们所需的值存在于OUTPUT访问器中。
例如:在2D问题(数据,PERIODS)中 - function2在T = 4时需要function1的结果。但工作项目并非全部同步。所以也许值函数2需要存在,也许不存在。解决方案是确保通过在所有被调用的函数周围放置for循环并从2D问题转到1D(看起来真的很糟糕,2D组织可能很棒..但我没有找到任何方法通过全局同步所有线程存储器)
我必须使用更少内存的第一个想法是使用参数T = t调用内核函数的481次。因此输出阵列的重量将比现在减少481,我可以增加481个数据。但是要使用这个解决方案,我必须分解我的for循环,这是我猜的不可能。 (就像我说的:因为函数2可能需要函数1结果,例如T = 4)
如果您有任何想法或解决方案,我会很高兴听到它们。
答案 0 :(得分:0)
我现在正在开发一个使用GPU的项目,这会让我的结果变慢 比CPU。原因是我将一个太小的数据阵列排入 输入(长度= 1024)
假设您的gpu具有异步dma模块,为什么不将它实现为流水线?上传第一次迭代,第一次计算第一次上传,下载第一次同时计算第二次也上传第三次,下载2次+计算3次+上传4次,下载3次+计算4次+上传5.这应该至少隐藏读取或写入gpu。
我想将更多数据排入队列,但由于内存问题,我已经陷入困境 用法。我在我的内核283函数内部计算,每个函数都进行了评估 481期。
因此,为了取回我的结果,我必须创建一个大小的数组 N(这里1024)x 481 x 283的双打(因为283函数返回 双倍价值)
假设"函数"的递归性如果不超过GB,您可以将每个类型的请求排入队列
OUTPUT[thread_num], period_num, f_num) = function_f_num(data, period_num);
当你只需要它时(而不是计算一切)进入一个列表。然后,当队列达到大约1M个元素时,将其上传到gpu。添加伪递归(使用带有post-fix的多重复制内核名称或支持内核的一些半堆栈结构)来查找需要递归的任何元素。可以将不可比较的元素添加到新列表中,而不是递归性,在主机端具有递归以完成所有子列表。这也应该为软件提供明确的多GPU使用优势,因为您可以在不同的gpus中计算多个队列。或者,您可以简单地使用gpu的主机指针来使用所有主机端缓冲区。看看 CL_MEM_USE_HOST_PTR 参数。