/*
* 源代码来自 炼数成金教程
* 给出任意一个一维数组
* 新数组中每个元素都等于源数组中位置排在它前面的所有元素的和
* */
#include <iomanip>
#include<iostream>
using namespace std;
__global__ void scan(float *d_out, float *d_in)
{
int idx = threadIdx.x + blockIdx.x * blockDim.x;
float out = 0.00f;
//原始数据赋值给d_out[idx]
d_out[idx] = d_in[idx];
__syncthreads(); //因为下一步要依赖上一步的结果,要同步,保证所有线程都完成赋值操作
//
for(int interpre=1;interpre<sizeof(d_in);interpre*=2)
{
if(idx-interpre>=0)
{
out = d_out[idx]+d_out[idx-interpre];
}
__syncthreads();
if(idx-interpre>=0)
{
d_out[idx] = out;
out = 0.00f;
}
}
}
int main()
{
const int ARRAY_SIZE = 20;
int ARRAY_BYTES = ARRAY_SIZE * sizeof(float);
float h_in[ARRAY_SIZE];
float h_out[ARRAY_SIZE];
float *d_in;
float *d_out;
//设置源数组,并打印
cout<<"源数组:"<<endl;
for(int i = 0; i<ARRAY_SIZE; i++)
{
h_in[i] = i;
cout<<setw(20)<<h_in[i]<<" ";
if( (i+1)%4 == 0 )
{
cout<<endl;
}
}
//设备端变量分配内存
cudaMalloc( (void **) &d_in, ARRAY_BYTES );
cudaMalloc( (void **) &d_out, ARRAY_BYTES );
//主机端变量赋值给设备端变量
cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);
//执行设备端代码
scan<<< 1, ARRAY_SIZE >>>(d_out, d_in);
//设备端变量赋值给主机端变量
cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);
//释放设备端内存
cudaFree(d_in);
cudaFree(d_out);
//打印变量
cout<<endl<<"新数组中每个元素都等于源数组中位置排在它前面的所有元素的和: "<<endl;
for(int i = 0; i<ARRAY_SIZE; i++)
{
cout<<setw(20)<<h_out[i]<<" ";
if( (i+1)%4 == 0 )
{
cout<<endl;
}
}
return 0;
}
///
结果如下
///
源数组:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19
新数组中每个元素都等于源数组中位置排在它前面的所有元素的和:
0 1 3 6
10 15 21 28
36 44 52 60
68 76 84 92
100 108 116 124
///
算法示意图: