Cuda GPU实现中的顺序操作
我必须在GPU中实现以下算法Cuda GPU实现中的顺序操作,cuda,parallel-processing,gpu,Cuda,Parallel Processing,Gpu,我必须在GPU中实现以下算法 for(int I = 0; I < 1000; I++){ VAR1[I+1] = VAR1[I] + VAR2[2*K+(I-1)];//K is a constant } 这属于一类问题,称为。根据递归关系的结构,可能存在描述如何单独计算每个元素(即并行计算,无递归)的封闭形式解决方案。早期的开创性论文之一(关于并行计算)是,并且存在将特定形式并行化的方法和策略 有时,递归关系非常简单,我们可以通过一点“检查”来识别一个封闭形式的公式或算法。这
for(int I = 0; I < 1000; I++){
VAR1[I+1] = VAR1[I] + VAR2[2*K+(I-1)];//K is a constant
}
这属于一类问题,称为。根据递归关系的结构,可能存在描述如何单独计算每个元素(即并行计算,无递归)的封闭形式解决方案。早期的开创性论文之一(关于并行计算)是,并且存在将特定形式并行化的方法和策略 有时,递归关系非常简单,我们可以通过一点“检查”来识别一个封闭形式的公式或算法。这给了这个想法更多的处理 在您的例子中,我们看看是否可以通过绘制
VAR1
的前几个术语的样子,将以前的术语替换为新的术语来发现任何东西:
i VAR1[i]
___________________
0 1
1 1 + VAR2[2K-1]
2 1 + VAR2[2K-1] + VAR2[2K]
3 1 + VAR2[2K-1] + VAR2[2K] + VAR2[2K+1]
4 1 + VAR2[2K-1] + VAR2[2K] + VAR2[2K+1] + VAR2[2K+2]
...
希望您看到的是,上面的VAR2[]
术语遵循一种模式
这意味着可以通过以下方式给出一种可能的解决方法:
VAR1[i] = 1+prefix_sum(VAR2[2K + (i-2)]) (for i > 0) notes:(1) (2)
VAR1[i] = 1 (for i = 0)
现在,前缀和可以并行完成(这不是一个真正的完全独立的操作,但它可以并行化。我不想在这里就术语或纯度争论太多。我提供了一种可能的并行化方法,这不是唯一的方法。)在GPU上并行完成前缀和,我会使用一个图书馆,就像或。或者你可以,尽管我不推荐
注:
i
的偏移量,可能取决于使用包含的或排除的扫描或前缀和操作
VAR2
,以使其合理。然而,这个要求隐含在你的问题陈述中VAR2
索引项2K+(I-1)
只是表示到I
(2K-1
)的固定偏移量,因此出于演示目的,我们仅使用偏移量0,因此VAR2
只是与VAR1
相同域上的一个简单数组。为了演示,我将VAR2
定义为所有1
的数组。gpu并行计算发生在VAR1
向量中,CPU等效计算仅在CPU
变量中动态计算,以进行验证:
$ cat t1056.cu
#include <thrust/scan.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/transform.h>
#include <iostream>
const int dsize = 1000;
using namespace thrust::placeholders;
int main(){
thrust::device_vector<int> VAR2(dsize, 1); // initialize VAR2 array to all 1's
thrust::device_vector<int> VAR1(dsize);
thrust::exclusive_scan(VAR2.begin(), VAR2.end(), VAR1.begin(), 0); // put prefix sum of VAR2 into VAR1
thrust::transform(VAR1.begin(), VAR1.end(), VAR1.begin(), _1 += 1); // add 1 to every term
int cpu = 1;
for (int i = 1; i < dsize; i++){
int gpu = VAR1[i];
cpu += VAR2[i];
if (cpu != gpu) {std::cout << "mismatch at: " << i << " was: " << gpu << " should be: " << cpu << std::endl; return 1;}
}
std::cout << "Success!" << std::endl;
return 0;
}
$ nvcc -o t1056 t1056.cu
$ ./t1056
Success!
$
$cat t1056.cu
#包括
#包括
#包括
#包括
#包括
常数int dsize=1000;
使用命名空间推力::占位符;
int main(){
推力::device_vector VAR2(dsize,1);//将VAR2数组初始化为所有1
推力:设备矢量VAR1(dsize);
独占扫描(VAR2.begin(),VAR2.end(),VAR1.begin(),0);//将VAR2的前缀和放入VAR1
推力::变换(VAR1.begin(),VAR1.end(),VAR1.begin(),_1+=1);//向每个术语添加1
int cpu=1;
对于(int i=1;i 如果(cpu!=gpu){std::cout这属于一类问题。根据递归关系的结构,可能存在描述如何单独计算每个元素(即并行计算,无递归)的闭式解。早期开创性论文之一(关于并行计算)是的,并且存在并行化特定形式的方法和策略
有时,递归关系非常简单,我们可以通过一点“检查”来识别一个封闭形式的公式或算法。这给了这个想法更多的处理
在您的例子中,我们看看是否可以通过绘制VAR1
的前几个术语的样子,将以前的术语替换为新的术语来发现任何东西:
i VAR1[i]
___________________
0 1
1 1 + VAR2[2K-1]
2 1 + VAR2[2K-1] + VAR2[2K]
3 1 + VAR2[2K-1] + VAR2[2K] + VAR2[2K+1]
4 1 + VAR2[2K-1] + VAR2[2K] + VAR2[2K+1] + VAR2[2K+2]
...
希望您看到的是,上面的VAR2[]
术语遵循一种模式
这意味着可以通过以下方式给出一种可能的解决方法:
VAR1[i] = 1+prefix_sum(VAR2[2K + (i-2)]) (for i > 0) notes:(1) (2)
VAR1[i] = 1 (for i = 0)
现在,前缀和可以并行完成(这不是一个真正完全独立的操作,但它可以并行化。我不想在这里对术语或纯度争论太多。我为您所述的问题提供一种可能的并行化方法,而不是唯一的方法。)要在GPU上并行进行前缀求和,我会使用像或这样的库。或者你也可以,尽管我不推荐这样做
注:
使用-1或-2作为前缀和的i
的偏移量,可能取决于使用包含的或排除的扫描或前缀和操作
VAR2
必须在适当的域上定义,以使其合理。但是,该要求隐含在您的问题陈述中
这里是一个简单的示例。在这种情况下,因为VAR2
索引项2K+(I-1)
只表示I
的固定偏移量(2K-1
),我们只是使用0的偏移量进行演示,因此VAR2
只是与VAR1
相同域上的一个简单数组。为了演示,我将VAR2
定义为所有1
的数组。gpu并行计算发生在VAR1
向量中,CPU等价物出于验证目的,只需在cpu
变量中动态计算计算:
$ cat t1056.cu
#include <thrust/scan.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/transform.h>
#include <iostream>
const int dsize = 1000;
using namespace thrust::placeholders;
int main(){
thrust::device_vector<int> VAR2(dsize, 1); // initialize VAR2 array to all 1's
thrust::device_vector<int> VAR1(dsize);
thrust::exclusive_scan(VAR2.begin(), VAR2.end(), VAR1.begin(), 0); // put prefix sum of VAR2 into VAR1
thrust::transform(VAR1.begin(), VAR1.end(), VAR1.begin(), _1 += 1); // add 1 to every term
int cpu = 1;
for (int i = 1; i < dsize; i++){
int gpu = VAR1[i];
cpu += VAR2[i];
if (cpu != gpu) {std::cout << "mismatch at: " << i << " was: " << gpu << " should be: " << cpu << std::endl; return 1;}
}
std::cout << "Success!" << std::endl;
return 0;
}
$ nvcc -o t1056 t1056.cu
$ ./t1056
Success!
$
$cat t1056.cu
#包括
#包括
#包括
#包括
#包括
常数int dsize=1000;
使用命名空间推力::占位符;
int main(){
推力::device_vector VAR2(dsize,1);//将VAR2数组初始化为所有1
推力:设备矢量VAR1(dsize);
独占扫描(VAR2.begin(),VAR2.end(),VAR1.begin(),0);//将VAR2的前缀和放入VAR1
推力::变换(VAR1.begin(),VAR1.end(),VAR1.begin(),_1+=1);//向每个术语添加1
int cpu=1;
对于(int i=1;i