Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在运行时根据CUDA计算能力切换主机功能_C++_C_Cuda_Gpgpu - Fatal编程技术网

C++ 在运行时根据CUDA计算能力切换主机功能

C++ 在运行时根据CUDA计算能力切换主机功能,c++,c,cuda,gpgpu,C++,C,Cuda,Gpgpu,我目前有一个主机函数,其中包括一个循环和各种CUBLAS调用。现在可以访问CC3.5设备了,我可以使用动态并行编写一个效率更高的内核。但是,我希望继续支持CC

我目前有一个主机函数,其中包括一个循环和各种CUBLAS调用。现在可以访问CC3.5设备了,我可以使用动态并行编写一个效率更高的内核。但是,我希望继续支持CC<3.5设备的旧功能。我现在支持使用两个gencode在同一二进制文件中使用多个设备:

-gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35
我希望继续生成一个支持这两种体系结构的二进制文件,但我想不出在主机代码中切换这种文件的方法。NVCC当然不能为主机AFAIK上的任何内容生成编译后的代码映像

这是不好的(也是非常丑陋的),因为为CC<3.5构建的用户将无法使用3.5功能构建内核:

cudaGetDevice (&current_device);
cudaGetDeviceProperties (&current_device_properties, current_device);
if (current_device_properties.major < 3 && ... etc) {
  ...
}
else ...
cudaGetDevice(¤t_设备);
CUDAGetDeviceProperty(当前设备属性和当前设备属性,当前设备);
如果(当前设备属性.major<3&&…等){
...
}
其他的
__CUDACC_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


我猜这是不可能的,我将不得不开始编译单独的二进制文件并在预处理器中切换架构。但是,如果有人能想到什么,那就太好了。

这取决于你的目标是什么。你好像在问两个不同的案子

首先,如果您认为用户可能使用不支持CC 3.5的nvcc编译代码,则需要在CUDA_ARCH上使用预处理器检查来测试计算能力,并防止其尝试编译不支持的代码

其次,如果您打算编译代码以同时包含CC 3.5和更低版本功能的实现,那么应该使用cudaGetDeviceProperties检查,正如您已经注意到的那样,以选择正确的主机实现

如果您希望同时使用这两种方法,则可能需要使用与此类似的实现

cudaGetDevice (&current_device);
cudaGetDeviceProperties (&cdp, current_device);
if (cdp.major < 3 || (cdp.major >= 3 &&  cdp.minor < 5)) {
  //loop and CUBLAS
}else {
  kernel35<<<>>>();
}
__global void kernel35(){
  #if (__CUDA_ARCH__ >=350 )
  ...
  #else
  //stub
  #endif
}
另外,我想您已经测试过新内核更高效,但是如果提前知道迭代次数,动态并行性几乎总是比从CPU正确启动慢。在我的测试中,这一比例高达40%,因此我建议在为开普勒GPU切换之前彻底测试性能

编辑: 我突然想到,更兼容、更安全的选择是这样表述第二部分

cudaGetDevice (&current_device);
cudaGetDeviceProperties (&cdp, current_device);
if (cdp.major < 3 || (cdp.major >= 3 &&  cdp.minor < 5)) {
  //loop and CUBLAS
}else {
  kernel35<<<>>>();
}
__global void kernel35(){
  #if (__CUDA_ARCH__ >=350 )
  ...
  #else
  //stub
  #endif
}

我确实希望两者同时出现。我以前的想法错误是CUDA_ARCH_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。谢谢,这会很好。现在我接受了,我读得更透彻了,我看到了你关于DP比正确的CPU内核启动慢的评论。这很有趣。我已经测试了我的DP,它大大加快了速度。我确实知道提前迭代的次数,我的函数非常适合标准内核,只是它涉及三个CUBLAS调用,如果没有CC\geq 3.5/DP,就无法从内核中调用。如果我错了,请告诉我。实际上,你已经引导我做了正确的事情。因为在我的例子中,每个线程都是完全隔离的,我的CUBLAS调用都是相对简单的1级调用,所以我可以自己在每个线程的本地内核中编写简单的迭代blas例程。我认为这应该可以很好地工作,我从来没有想过要这么做。在您描述的情况下,使用动态并行可能会加快速度。我提到的例子是用它来代替CPU上的循环,比如对于1-100{kernel()},,在这种情况下,CPU控制速度更快。需要检查的一件事是循环中是否有cudaThreadSynchronize调用。如果您这样做了,请尝试删除它,如果动态并行性适合您,那么您可能实际上并不需要它,并且删除它可能会显著提高性能。