如何在内核调用中将数据保存在快速GPU内存(l1 /共享)中?

时间:2018-04-26 23:48:04

标签: cuda

如何跨内核调用将数据保存在快速GPU内存中?

让我们假设,我需要回答100万个查询,每个查询都有大约1.5MB的数据,这些数据可以在调用中重复使用,并且每个查询都有大约8KB的数据。

一种方法是为每个查询启动内核,每次将1.5MB + 8KB的数据复制到共享内存。但是,我花了很多时间来复制1.5MB的数据,这些数据确实可以在查询中持续存在。

另一种方法是“循环”GPU线程(参见https://stackoverflow.com/a/49957384/3738356)。这涉及启动一个内核,立即将1.5MB数据复制到共享内存。然后内核等待请求进入,等待8KB数据出现,然后再进行每次迭代。看起来CUDA似乎不是以这种方式使用的。如果只使用托管内存,并且使用volatile +单调递增计数器进行同步,则仍然无法保证在您阅读时计算答案所需的数据将在GPU上。您可以使用-42之类的虚拟值为内存中的值设置种子值,这些值表示该值尚未进入GPU(通过缓存/托管内存机制),然后忙等待,直到值变为有效。从理论上讲,这应该有效。但是,我有足够的记忆错误,我现在已经放弃了,而且我已经追求....

另一种方法仍然使用回收线程,而是通过cudaMemcpyAsync,cuda流,cuda事件以及仍有一些易变+单调增加的计数器同步数据。我听说我需要固定每个查询新鲜的8KB数据,以便cudaMemcpyAsync正常工作。但是,异步副本不会被阻止 - 它的效果是不可观察的。我怀疑有足够的勇气,我也能做到这一点。

然而,以上所有让我觉得“我做错了。” 如何在GPU缓存中保留极其可重复使用的数据,以便可以从一个查询访问到下一个查询?

1 个答案:

答案 0 :(得分:1)

  • 首先要观察流和异步复制的影响 你肯定需要固定主机内存。然后你可以观察 并发内核调用“几乎”同时发生。 我宁愿使用异步复制,因为它让我感觉掌控 情况。
  • 其次,你可以坚持全局内存中的数据并加载 它在你需要的时候在共享内存中。据我所知,分享 内存只有内核本身知道并在之后处理 终止。在内核运行时尝试使用Async副本 相应地同步流。别忘了__syncthreads() 加载到共享内存后。我希望它有所帮助。