CUDA:设备和代码可以并行运行直到生命周期,乒乓数据?

CUDA:设备和代码可以并行运行直到生命周期,乒乓数据?,cuda,ipc,Cuda,Ipc,我正在用Cuda编程矩阵向量乘法。矩阵以块为单位,因此每个线程可以在共享内存中保存矩阵的一块(作为线程局部变量)。我还将向量作为参数发送,乘法是分块执行的,没有问题。但这是一个依赖时间的问题。我必须用相同的矩阵计算矩阵向量积,但每个时间片的向量不同。因此,每次产品评估都调用内核是一种浪费,会导致矩阵块从图形卡的全局内存复制到共享内存。我认为我可以进行一次内核调用,并使其始终保持活动状态,从而不会丢失线程局部变量。向量可以作为主机中的映射内存分配,比如V。现在内核将其相乘,保存在另一个映射区域中,

我正在用Cuda编程矩阵向量乘法。矩阵以块为单位,因此每个线程可以在共享内存中保存矩阵的一块(作为线程局部变量)。我还将向量作为参数发送,乘法是分块执行的,没有问题。但这是一个依赖时间的问题。我必须用相同的矩阵计算矩阵向量积,但每个时间片的向量不同。因此,每次产品评估都调用内核是一种浪费,会导致矩阵块从图形卡的全局内存复制到共享内存。我认为我可以进行一次内核调用,并使其始终保持活动状态,从而不会丢失线程局部变量。向量可以作为主机中的映射内存分配,比如V。现在内核将其相乘,保存在另一个映射区域中,比如P,设置一个标志(另一个整数映射内存)。主机轮询该标志,一旦设置了该标志,它将显示来自P的乘积,将新向量加载到V中,并重置该标志。内核还轮询标志,查看重置、乘法、将产品保存在P中并设置标志

我写了一个较小的加法程序,看看这样的进程间通信是否有效,但它不起作用。问题是,当内核将任何内容写入映射内存时,主机中的内存不会更新,直到主机调用cudaThreadSynchronize();但是,如果线程同步不能发生,只要内核在该标志上进行轮询。有办法摆脱这种局面吗

有没有其他非难看的方法来实现这样的进程间通信。 当然,手册说映射内存有助于分摊延迟,即一次性复制。因为他们没有解释施加这种限制的潜在机制,所以我尝试一下这个想法

欢迎任何帮助

谢谢,


Elan.

我不确定我是否完全理解您的问题,但是是的,您可以有多个并发内核处于活动状态

来自CUDA计算指南v。3.2第38页:

一些计算能力为2.x的设备可以执行多个内核 同时应用程序可以通过调用 cudaGetDeviceProperties()并检查concurrentKernels 财产

我的问题是为什么要使用多个内核

我认为你需要重新阅读CUDA指南(见上文)。听起来您想要做的是一个具有多个块/线程的单个内核,每个块都有自己的共享内存块。接下来,您需要计算每个块使用的元素有多大。请记住,您需要两块内存和一个乘积(3个大小相等的二维正方形矩阵)。要执行此操作,请查询您的设备并获取计算容量,并阅读上述指南以确定共享内存的结果量

然后使用如下代码:

if (ComputeCapability >= 2.0)
   {
      NumberOfSharedValues = (32768/GetSize(Dummy));
      FullUseageThreadsPerBlock = 512;
      MaxBlocksPerSM = 3;
   }
   else
   {
      //Tot. Shared mem / Size per var / Number of Arrays
      NumberOfSharedValues = (16384/GetSize(Dummy)/3);

      //CC1.2 && CC1.3
      if (ComputeCapability >= 1.2)
      {
         FullUseageThreadsPerBlock = 512;
         MaxBlocksPerSM = 2;
      }  
      else  //CC1.0 && CC1.1
      {
         FullUseageThreadsPerBlock = 256;
         MaxBlocksPerSM = 3;
      }   
   }   
其中,
Dummy
是模板类型,我编写了函数以返回CUDA中常见模板类型(例如int、float、double)的大小(例如,在C中,int通常为16位,在CUDA中为32位)

将阵列复制到设备的全局内存中

然后取
numberOfSharedValue
变量的平方根,编写一个内核,在该长度的共享内存中声明三个数组(两个“块”和乘积)

让内核将要乘法的块复制到共享内存中,进行乘法,然后将得到的“乘积”块写回全局内存

最后,将全局产品阵列读回主机

瞧,我想这应该对你有好处

请记住,您将分配的上述共享内存是单个多处理器的可用内存量(由于您的每个块都分配了这么多内存,因此块=#多处理器),因此您可以同时处理的元素的总大小将是您有多少多处理器的函数,又是一个可查询的数量

另外请注意,您可能希望使用
cuMemGetInfo
获取可用内存量,以确保您可以将who数组放入全局内存

再次阅读指南并查看NVIDIA发布的示例对于理解设备上的内存层次结构和编写良好的内核至关重要


希望有帮助

我不确定我是否完全理解您的问题,但是是的,您可以有多个并发内核处于活动状态

来自CUDA计算指南v。3.2第38页:

一些计算能力为2.x的设备可以执行多个内核 同时应用程序可以通过调用 cudaGetDeviceProperties()并检查concurrentKernels 财产

我的问题是为什么要使用多个内核

我认为你需要重新阅读CUDA指南(见上文)。听起来您想要做的是一个具有多个块/线程的单个内核,每个块都有自己的共享内存块。接下来,您需要计算每个块使用的元素有多大。请记住,您需要两块内存和一个乘积(3个大小相等的二维正方形矩阵)。要执行此操作,请查询您的设备并获取计算容量,并阅读上述指南以确定共享内存的结果量

然后使用如下代码:

if (ComputeCapability >= 2.0)
   {
      NumberOfSharedValues = (32768/GetSize(Dummy));
      FullUseageThreadsPerBlock = 512;
      MaxBlocksPerSM = 3;
   }
   else
   {
      //Tot. Shared mem / Size per var / Number of Arrays
      NumberOfSharedValues = (16384/GetSize(Dummy)/3);

      //CC1.2 && CC1.3
      if (ComputeCapability >= 1.2)
      {
         FullUseageThreadsPerBlock = 512;
         MaxBlocksPerSM = 2;
      }  
      else  //CC1.0 && CC1.1
      {
         FullUseageThreadsPerBlock = 256;
         MaxBlocksPerSM = 3;
      }   
   }   
其中,
Dummy
是模板类型,我编写了函数以返回CUDA中常见模板类型(例如int、float、double)的大小(例如,在C中,int通常为16位,在CUDA中为32位)

将阵列复制到设备的全局内存中

然后取
numberOfSharedValue
变量的平方根,编写一个内核,在该长度的共享内存中声明三个数组(两个“块”和乘积)

让内核将区块复制到共享中