Performance CUDA性能怀疑
由于我没有收到CUDA论坛的回复,我将在这里尝试: 在CUDA做了一些程序之后,我现在开始获得它们的有效带宽。然而,我有一些奇怪的结果,例如在下面的代码中,我可以对向量中的所有元素求和(不考虑维度),使用展开代码和“正常”代码的带宽似乎具有相同的中值结果(大约3000 Gb/s) 我不知道我是否做错了什么(好吧,程序运行得很好),但从我目前所读到的来看,展开代码应该有更高的带宽Performance CUDA性能怀疑,performance,cuda,bandwidth,gpu,Performance,Cuda,Bandwidth,Gpu,由于我没有收到CUDA论坛的回复,我将在这里尝试: 在CUDA做了一些程序之后,我现在开始获得它们的有效带宽。然而,我有一些奇怪的结果,例如在下面的代码中,我可以对向量中的所有元素求和(不考虑维度),使用展开代码和“正常”代码的带宽似乎具有相同的中值结果(大约3000 Gb/s) 我不知道我是否做错了什么(好吧,程序运行得很好),但从我目前所读到的来看,展开代码应该有更高的带宽 #include <stdio.h> #include <limits.h> #include
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <math.h>
#define elements 1000
#define blocksize 16
__global__ void vecsumkernel(float*input, float*output,int nelements){
__shared__ float psum[blocksize];
int tid=threadIdx.x;
if(tid + blockDim.x * blockIdx.x < nelements)
psum[tid]=input[tid+blockDim.x*blockIdx.x];
else
psum[tid]=0.0f;
__syncthreads();
//WITHOUT UNROLL
int stride;
for(stride=blockDim.x/2;stride>0;stride>>=1){
if(tid<stride)
psum[tid]+=psum[tid+stride];
__syncthreads();
}
if(tid==0)
output[blockIdx.x]=psum[0];
//WITH UNROLL
/*
if(blocksize>=512 && tid<256) psum[tid]+=psum[tid+256];__syncthreads();
if(blocksize>=256 && tid<128) psum[tid]+=psum[tid+128];__syncthreads();
if(blocksize>=128 && tid<64) psum[tid]+=psum[tid+64];__syncthreads();
if (tid < 32) {
if (blocksize >= 64) psum[tid] += psum[tid + 32];
if (blocksize >= 32) psum[tid] += psum[tid + 16];
if (blocksize >= 16) psum[tid] += psum[tid + 8];
if (blocksize >= 8) psum[tid] += psum[tid + 4];
if (blocksize >= 4) psum[tid] += psum[tid + 2];
if (blocksize >= 2) psum[tid] += psum[tid + 1];
}*/
if(tid==0)
output[blockIdx.x]=psum[0];
}
void vecsumv2(float*input, float*output, int nelements){
dim3 dimBlock(blocksize,1,1);
int i;
for(i=((int)ceil((double)(nelements)/(double)blocksize))*blocksize;i>1;i(int)ceil((double)i/(double)blocksize)){
dim3 dimGrid((int)ceil((double)i/(double)blocksize),1,1);
printf("\ni=%d\ndimgrid=%u\n ",i,dimGrid.x);
vecsumkernel<<<dimGrid,dimBlock>>>(i==((int)ceil((double)(nelements)/(double)blocksize))*blocksize ?input:output,output,i==((int)ceil((double)(nelements)/(double)blocksize))*blocksize ? elements:i);
}
}
void printVec(float*vec,int dim){
printf("\n{");
for(int i=0;i<dim;i++)
printf("%f ",vec[i]);
printf("}\n");
}
int main(){
cudaEvent_t evstart, evstop;
cudaEventCreate(&evstart);
cudaEventCreate(&evstop);
float*input=(float*)malloc(sizeof(float)*(elements));
for(int i=0;i<elements;i++)
input[i]=(float) i;
float*output=(float*)malloc(sizeof(float)*elements);
float *input_d,*output_d;
cudaMalloc((void**)&input_d,elements*sizeof(float));
cudaMalloc((void**)&output_d,elements*sizeof(float));
cudaMemcpy(input_d,input,elements*sizeof(float),cudaMemcpyHostToDevice);
cudaEventRecord(evstart,0);
vecsumv2(input_d,output_d,elements);
cudaEventRecord(evstop,0);
cudaEventSynchronize(evstop);
float time;
cudaEventElapsedTime(&time,evstart,evstop);
printf("\ntempo gasto:%f\n",time);
float Bandwidth=((1000*4*2)/10^9)/time;
printf("\n Bandwidth:%f Gb/s\n",Bandwidth);
cudaMemcpy(output,output_d,elements*sizeof(float),cudaMemcpyDeviceToHost);
cudaFree(input_d);
cudaFree(output_d);
printf("soma do vector");
printVec(output,4);
}
#包括
#包括
#包括
#包括
#定义元素1000
#定义块大小16
__全局_uu; void vecsumkernel(浮点*输入、浮点*输出、整数元素){
__共享浮点psum[块大小];
int tid=threadIdx.x;
if(tid+BLOCKIM.x*blockIdx.x0;步幅>>=1){
如果(tid=512&&tid=256&&tid=128&&tid=64)psum[tid]+=psum[tid+32];
如果(块大小>=32)psum[tid]+=psum[tid+16];
如果(块大小>=16)psum[tid]+=psum[tid+8];
如果(块大小>=8)psum[tid]+=psum[tid+4];
如果(块大小>=4)psum[tid]+=psum[tid+2];
如果(块大小>=2)psum[tid]+=psum[tid+1];
}*/
如果(tid==0)
输出[blockIdx.x]=psum[0];
}
void vecsumv2(浮点*输入、浮点*输出、整数元素){
dim3 dimBlock(块大小,1,1);
int i;
对于(i=((int)cell((double)(neelements)/(double)blocksize))*blocksize;i>1;i(int)cell((double)i/(double)blocksize)){
dim3 dimGrid((int)ceil((双)i/(双)块大小),1,1;
printf(“\ni=%d\ndimgrid=%u\n”,i,dimGrid.x);
vecsumkernel(i=((int)cell((double)(neelements)/(double)blocksize))*blocksize?输入:输出,i=((int)cell((double)(neelements)/(double)blocksize))*blocksize?元素:i);
}
}
无效打印向量(浮点*向量,整数尺寸){
printf(“\n{”);
对于(int i=0;i展开的代码中有很多分支。我计算了另外十个分支。通常在GPU上的一个扭曲内进行分支是昂贵的,因为扭曲中的所有线程最终都会等待分支(分歧)
有关扭曲散度的详细信息,请参见此处:
您是否尝试使用探查器查看发生了什么情况?3000 Gb/s没有意义。PCIe在每个方向上的最大总线速度为8Gb/s
看看这篇文章,了解如何加快实现。
也考虑到这个库已经在模块中实现了,你的未展开代码无效。对于<代码> Strud我看到你在内核中做减法和。这是一个很好的NVIDIA优化GPU的方法。你会发现,相同的代码,它的吞吐量超过2 Gb/s,被优化到63 Gb/s 在本指南中。我从Nvidia Reduce.pdf中获取了展开代码。我不知道探查器的用途是什么(我一个月前才开始与cuda合作,计算机工程/编程不是我的领域)。此外,如何计算10个额外分支?我正在计算“如果”s、 你不是每次都做10次,但是有很多可能的代码路径,每个分支都可能导致扭曲发散。我认为这个值非常高,但我发现带宽是用我在CUDA编程指南上看到的公式计算的:float带宽=((1000*4*2)/10^9)/time;//BW=(Bytesread+bytesrite)/10 ^ 9/时间与展开代码,IM检查我的代码与英伟达还原.PDF,我认为代码是相同的= /我相信你说的是真的看了看代码我不明白为什么有些线程不进入for循环。我看到只有一些线程(tid我明白你说的,如果步幅是ex 16,tid从0到16进入for,而其他人没有(我想这就是你的意思)。我认为分支冬青在if条件下发生,但我不知道这是否有问题。我知道的是,它应该效率较低