当前代码的缺点:
1、只能在同一个block做运算
2、只能做所求个数组数为偶数的计算
#include "device_functions.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "stdlib.h"
#include <iostream>
using namespace std;
//返回thread和block
int getThreadNum()
{
cudaDeviceProp prop;//cudaDeviceProp的一个对象
int count = 0;//GPU的个数
cudaGetDeviceCount(&count);
std::cout << "gpu 的个数:" << count << '\n';
cudaGetDeviceProperties(&prop, 0);//第二参数为那个gpu
cout << "最大线程数:" << prop.maxThreadsPerBlock << endl;
cout << "最大网格类型:" << prop.maxGridSize[0] << '\t' << prop.maxGridSize[1] << '\t' << prop.maxGridSize[2] << endl;
return prop.maxThreadsPerBlock;
}
//形参:枚举类型
//判断是否成功分配内存
void GetCudaCalError(cudaError err)
{
if (err != cudaSuccess)
{
cout << "分配内存失败!程序结束!";
}
return;
}
//这个函数有局限性:不能放到多个block上运行
__global__ void sumReduced(float*aGpu, float*sumGpu, int countNum)
{
const int id = threadIdx.x;
//定义一个共享内存
__shared__ float sData[16];
//为其赋值
sData[id] = aGpu[id];
//等待每个线程赋值完成
__syncthreads();
//实现归约求和
/*
1、每个数和当前索引加上总数一半的值相加,如果超出最大索引数就加0
2、等到所有线程计算完毕
3、线程数减半,直到减到1(这个1是现实中的1,计算机中的1为0)
*/
for (int i = countNum /2; i > 0; i /= 2)
{
if (id < i)
{
sData[id] += sData[id + i];
}
__syncthreads();
}
if (id == 0)
{
sumGpu[0] = sData[0];
}
}
int main()
{
float a[16];
float asum = 0;
for (int i = 0; i < 16; ++i)
{
a[i] = i * (i + 1);
}
//定义Device上的内存
float *aGpu = 0;
float *sumGpu = 0;
//为其开辟内存
GetCudaCalError(cudaMalloc(&aGpu, 16 * sizeof(float)));
GetCudaCalError(cudaMalloc(&sumGpu, 1 * sizeof(float)));
//给aGpu 赋值
cudaMemcpy(aGpu, a, 16 * sizeof(float), cudaMemcpyHostToDevice);
//开一个block,每个block里面有16个thread
sumReduced << <1, 16 >> > (aGpu, sumGpu,16);
//将结果传回host
cudaMemcpy(&asum, sumGpu, 1 * sizeof(float), cudaMemcpyDeviceToHost);
cudaFree(aGpu);
cudaFree(sumGpu);
cout << "cuda数组和为:" << asum << endl;
float testSum = 0;
for (int i = 0; i < 16; ++i)
{
testSum += a[i];
}
cout << "for数组和为:" << testSum << endl;
}