gpt4 book ai didi

c++ - 删除CUDA依赖项?

转载 作者:行者123 更新时间:2023-11-28 05:54:48 26 4
gpt4 key购买 nike

我感兴趣的开源C ++ / Qt应用程序取决于CUDA。我的Macbook Pro(2014年中)有现货的Intel Iris Pro,没有NVidia显卡。当然,预构建的应用程序将无法运行。

我找到了这个模拟器:https://github.com/gtcasl/gpuocelot-但它仅针对Linux进行了测试,并且存在一些未在Mac上编译的未解决问题。

我有资料来源-我可以用较慢的处理成本来替换CUDA依赖项吗?我希望有类似的东西


重命名文件扩展名:.cu到.cpp
从make文件中删除CUDA引用
用等效的c ++ std lib头替换CUDA头
调整makefile,根据需要添加缺少的库引用
使用c ++代码(可能是Ocelot编写的)修复剩余的缺少的函数调用(希望只有一个或两个)


但是,恐怕不是那么简单。开始之前,我想进行一次健康检查。

最佳答案

在一般情况下,我认为没有“去CUDA-fy”应用程序的具体路线图。正如我认为没有特定的“机械”路线图来“ CUDA-fy”应用程序一样,我也没有找到一般的编程问题的特定路线图。

此外,我认为拟议的路线图存在缺陷。仅举一个例子,一个.cu文件通常将具有特定于CUDA的引用,而用于编译.cpp代码的普通c ++编译器将不允许这些引用。其中一些引用可能是依赖于CUDA运行时API的项,例如cudaMalloccudaMemcpy,尽管它们可以通过普通的c ++编译器传递(它们只是库调用),但这并不明智。将这些保留在原处,以便删除CUDA字符的应用程序。此外,某些参考可能是CUDA特定的语言功能,例如通过__global____device__声明设备代码,或使用相应的语法<<<...>>>启动设备“内核”功能。这些不能通过普通的c ++编译器来传递,必须专门处理。此外,仅删除那些CUDA关键字和语法将不太可能产生有用的结果。

简而言之,必须重构代码。没有合理简明的路线图可以解释这样做的机械过程。我建议重构过程的复杂度应与将代码的非CUDA版本转换为CUDA版本的原始过程(如果有的话)大致相同。至少需要了解CUDA编程的一些非机械知识,才能理解CUDA的构造。

对于非常简单的CUDA代码,可能需要安排一些机械过程来取消对CUDA的编码。概括地说,基本的CUDA处理顺序如下:


为设备上的数据分配空间(可能使用cudaMalloc),并将数据复制到设备上(可能使用cudaMemcpy
启动在设备上运行的功能(__global__或“内核”功能)以处理数据并创建结果
将结果从设备复制回(也许再次使用cudaMemcpy


因此,一种简单的方法是:


消除cudaMalloc / cudaMemcpy操作,从而将感兴趣的数据以其原始形式保留在主机上
将cuda处理函数(内核)转换为对主机数据执行相同操作的普通c ++函数


由于CUDA是并行处理体系结构,一种将固有并行CUDA“内核”代码转换为普通c ++代码的方法(上述步骤2)将使用一个循环或一组循环。但是除此之外,根据代码实际在做什么,路线图趋向于趋于分歧。此外,线程间通信,非变换算法(例如缩减)以及CUDA内在函数或其他特定于语言的功能的使用将使步骤2大大复杂化。

例如,让我们采用一个非常简单的矢量ADD代码。用于此目的的CUDA内核代码将通过许多特性来区分,这些特性将使其易于与CUDA实现进行相互转换:


没有线程间通信。问题是“令人尴尬的平行”。每个线程完成的工作都独立于所有其他线程。这仅描述了CUDA代码的有限子集。
不需要或不使用任何CUDA特定语言功能或内在函数(除了全局唯一的线程索引变量),因此内核代码已经可以识别为几乎完全有效的c ++代码。同样,此特征可能仅描述CUDA代码的有限子集。


因此,矢量添加代码的CUDA版本可能如下所示(出于演示目的,已大大简化):

#include <stdio.h>
#define N 512
// perform c = a + b vector add
__global__ void vector_add(const float *a, const float *b, float *c){

int idx = threadIdx.x;
c[idx]=a[idx]+b[idx];
}

int main(){

float a[N] = {1};
float b[N] = {2};
float c[N] = {0};
float *d_a, *d_b, *d_c;
int dsize = N*sizeof(float);
cudaMalloc(&d_a, dsize); // step 1 of CUDA processing sequence
cudaMalloc(&d_b, dsize);
cudaMalloc(&d_c, dsize);
cudaMemcpy(d_a, a, dsize, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, b, dsize, cudaMemcpyHostToDevice);
vector_add<<<1,N>>>(d_a, d_b, d_c); // step 2
cudaMemcpy(c, d_c, dsize, cudaMemcpyDeviceToHost); // step 3
for (int i = 0; i < N; i++) if (c[i] != a[i]+b[i]) {printf("Fail!\n"); return 1;}
printf("Success!\n");
return 0;
}


我们看到上面的代码遵循典型的CUDA处理序列1-2-3,并且在注释中标记了每个步骤的开始。因此,我们的“ de-CUDA-fy”路线图再次是:


消除 cudaMalloc / cudaMemcpy操作,从而将感兴趣的数据以其原始形式保留在主机上
将cuda处理函数(内核)转换为对主机数据执行相同操作的普通c ++函数


对于第1步,我们实际上只是删除 cudaMalloccudaMemcpy行,而是计划直接在宿主代码中的 a[]b[]c[]变量上进行操作。然后,剩下的步骤是将 vector_add CUDA“内核”函数转换为普通的c ++函数。同样,必须了解一些CUDA基础知识,才能了解并行执行操作的程度。但是内核代码本身(除了使用 threadIdx.x内置CUDA变量之外)是完全有效的c ++代码,并且没有线程间通信或其他复杂因素。因此,普通的c ++实现可能只是内核代码,被放置在并行范围内的适当的for循环迭代中(在本例中为 N),并被放置在类似的c ++函数中:

 void vector_add(const float *a, const float *b, float *c){

for (int idx=0; idx < N; idx++)
c[idx]=a[idx]+b[idx];
}


结合以上步骤,我们需要(在这个简单的示例中):


删除 cudaMalloccudaMemcpy操作
用类似的普通c ++函数替换cuda内核代码
main中的内核调用修正为普通的c ++函数调用


这给了我们:

#include <stdio.h>
#define N 512
// perform c = a + b vector add
void vector_add(const float *a, const float *b, float *c){

for (int idx = 0; idx < N; idx++)
c[idx]=a[idx]+b[idx];
}

int main(){

float a[N] = {1};
float b[N] = {2};
float c[N] = {0};
vector_add(a, b, c);
for (int i = 0; i < N; i++) if (c[i] != a[i]+b[i]) {printf("Fail!\n"); return 1;}
printf("Success!\n");
return 0;
}


通过本示例进行操作的目的并不是要建议该过程通常如此简单。但有希望的是,该过程显然不是纯粹的机械过程,而是依赖于CUDA的某些知识,并且还需要一些实际的代码重构。不能简单地通过更改文件扩展名和修改一些函数调用来完成此操作。

其他一些评论:


许多笔记本电脑都具有支持CUDA(即NVIDIA)GPU。如果您有其中之一(我知道您没有,但是我将其包括在其中,以供其他可能阅读此书的人使用),则可以在其中运行CUDA代码。
如果您有一台可用的台式机,则可能不到100美元就可以在其中添加具有CUDA功能的GPU。
尝试利用仿真技术IMO并非一帆风顺,除非您可以以统包方式使用它。我认为,将仿真器中的点点滴滴塞进自己的应用程序中并非易事。
我相信在一般情况下,将CUDA代码转换为相应的OpenCL代码也不是一件容易的事。 (这里的动机是CUDA与OpenCL之间有很多相似之处,并且可能使OpenCL代码在笔记本电脑上运行,因为OpenCL代码通常可以在各种目标上运行,包括CPU和GPU)。两种技术之间有足够的差异,需要付出一些努力,这带来了额外的负担,要求他们一定程度地熟悉OpenCL和CUDA,而且您的问题的重点似乎是希望避免这些学习过程。

关于c++ - 删除CUDA依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34423660/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com