代码说明:
本次代码采用GPU运算一维卷积.其中你需要输入两个数据,第一个是n是一位数据长度,一个是m卷积因子长度,代码会随机生成两个数组用于计算卷积.
代码思路:在CPU中生成数据复制到GPU中,其中GPU有两个函数,一个是__global__ void juanji(int *d_a,int *d_b,int *d_c,int *d_data,int n, int m),这个函数就是核函数,用于开n - m + 1个线程,因为数据长度为n卷积因子长度为m,那么卷积次数为n-m+1次所以这个核函数就是开卷积次数的线程,在这个核函数中还有另外一个核函数用于嵌套__global__ void neiji(int *d_a,int *d_b,int *d_c,int *d_data,int n, int m,int IJdx);因为卷积也可以并行计算的.在每一个卷积线程下,又开了m个线程用于计算卷积和,这样这个代码相当于开了 m *(n -m+1)个线程.直接就把卷积和算出了.其中不足之处就是求和的时候用的依然是串行算法.这里是一个可优化的地方.需要花时间搞搞并行求和的算法.
实验结果:
请输入一位向量的长度:
6
请输入卷积因子长度:
3
h_a[0] = 10 h_a[1] = 10 h_a[2] = 5 h_a[3] = 10 h_a[4] = 5 h_a[5] = 7
h_b[0] = 7 h_b[1] = 10 h_b[2] = 9
h_c[0] = 215 h_c[1] = 210 h_c[2] = 180 h_c[3] = 183
运行结束
代码:
#include <iostream>
#include <cuda_runtime.h>
#include <stdlib.h>
#include <time.h>
__global__ void neiji(int *d_a,int *d_b,int *d_c,int *d_data,int n, int m,int IJdx)
{
int temp = 0;
int INdx = threadIdx.x;
d_data[IJdx * m + INdx] = d_a[IJdx + INdx] * d_b[INdx];
__syncthreads();
for(int i = 0; i < m; ++i)
{
temp += d_data[IJdx * m + i];
}
d_c[IJdx] = temp;
}
__global__ void juanji(int *d_a,int *d_b,int *d_c,int *d_data,int n, int m)
{
int IJdx = threadIdx.x;
neiji<<<1,m>>>(d_a,d_b,d_c,d_data,n,m,IJdx);
__syncthreads();
}
int main()
{
int blag = 1;
int m = 0, n = 0;
do{
std::cout << "请输入一位向量的长度:"<< std::endl;
std::cin >> n;
std::cout << "请输入卷积因子长度:" <<std::endl;
std::cin >> m;
if(m > n)
{
std::cout << "你输入的数据不合法,请重新输入!"<< std::endl;
}else{
blag = 0;
}
}while(blag);
/*****申请主机内存*******/
int *h_a,*h_b,*h_c;
h_a = (int*)malloc(sizeof(int) * n);
h_b = (int*)malloc(sizeof(int) * m);
h_c = (int*)malloc(sizeof(int) * (n - m + 1));
/******生成随机数据*******/
srand(time(NULL));
for(int i = 0; i < n; ++i)
{
h_a[i] = rand() % 11;
printf("h_a[%d] = %d\t",i,h_a[i]);
}
printf("\n");
for(int i = 0; i < m; ++i)
{
h_b[i] = rand() % 11;
printf("h_b[%d] = %d\t",i,h_b[i]);
}
printf("\n");
/******申请设备内存*************/
int *d_a,*d_b,*d_c,*d_data;
cudaMalloc((void**)&d_a,sizeof(int) * n);
cudaMalloc((void**)&d_b,sizeof(int) * m);
cudaMalloc((void**)&d_c,sizeof(int) * (n - m + 1));
cudaMalloc((void**)&d_data,sizeof(int) * m * (n - m + 1));
/******主机内存数据复制到设备内存中********/
cudaMemcpy(d_a,h_a,sizeof(int) * n,cudaMemcpyHostToDevice);
cudaMemcpy(d_b,h_b,sizeof(int) * m,cudaMemcpyHostToDevice);
/*******启动核函数*******/
juanji<<<1,n - m + 1>>>(d_a,d_b,d_c,d_data,n,m);
/*******设备内存数据复制到主机内存中********/
cudaMemcpy(h_c,d_c,sizeof(int) * (n - m + 1),cudaMemcpyDeviceToHost);
for(int i = 0; i < n - m + 1; ++i)
{
printf("h_c[%d] = %d\t",i,h_c[i]);
}
printf("\n");
/********释放内存********/
free(h_a);
free(h_b);
free(h_c);
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
std::cout << "运行结束" << std::endl;
return 0;
}