当前位置:  开发笔记 > 编程语言 > 正文

在我的机器上操作大型矢量时,CUDA推力变慢

如何解决《在我的机器上操作大型矢量时,CUDA推力变慢》经验,为你挑选了1个好方法。

我是一名CUDA初学者并正在阅读一些推力教程.我写了一个简单但非常有组织的代码并试图找出推力的加速度.(这个想法是否正确?).我尝试通过在cpu上添加数组并在gpu上添加device_vector,将两个向量(10000000 int)添加到另一个向量.

这是事情:

#include 
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include 
#include 

#define N 10000000
int main(void)
{
    float time_cpu;
    float time_gpu;
    int *a = new int[N];
    int *b = new int[N];
    int *c = new int[N];
    for(int i=0;i X(N);
    thrust::device_vector Y(N);
    thrust::device_vector Z(N);
    for(int i=0;i());
    cudaEventRecord(stop,0);
    cudaEventSynchronize(stop);
    float elapsedTime;
    cudaEventElapsedTime(&elapsedTime,start,stop);
    std::cout<<"Time to generate (thrust):"<

CPU结果看起来非常快,但是我的机器上的gpu运行速度非常慢(i5-2320,4G,GTX 560 Ti),CPU时间约为26,GPU时间约为30!我的代码中的愚蠢错误是否只是做错了?还是有更深层次的原因?

作为一个C++新手,我一遍又一遍地检查我的代码,并且仍然在GPU上使用推力较慢的时间,所以我做了一些实验来显示计算vectorAdd与五种不同方法的区别.我使用windows API QueryPerformanceFrequency()作为统一的时间测量方法.

每个实验看起来像这样:

f = large_interger.QuadPart;  
QueryPerformanceCounter(&large_interger);  
c1 = large_interger.QuadPart; 

for(int j=0;j<10;j++)
{
    for(int i=0;i

这是我__global__添加GPU阵列的简单功能:

__global__ void add(int *a, int *b, int *c)
{
    int tid=threadIdx.x+blockIdx.x*blockDim.x;
    while(tid

并且该函数被称为:

for(int j=0;j<10;j++)
{
    add<<<(N+127)/128,128>>>(dev_a,dev_b,dev_c);//GPU array adding
}   

我将向量a [N]和b [N]添加到向量c [N]中,循环次数为10次:

    在CPU上添加数组

    在CPU上添加std :: vector

    在CPU上添加thrust :: host_vector

    在GPU上添加thrust :: device_vector

    在GPU上添加数组.这是结果

N = 10000000

我得到了结果:

    CPU阵列添加268.992968ms

    CPU std :: vector添加1908.013595ms

    CPU Thrust :: host_vector添加10776.456803ms

    GPU Thrust :: device_vector添加297.156610ms

    GPU阵列增加5.210573ms

这让我很困惑,我不熟悉模板库的实现.容器和原始数据结构之间的性能真的差异很大吗?



1> Robert Crove..:

大多数执行时间都花费在初始化X [i]和Y [i]的循环中.虽然这是合法的,但它是初始化大型设备向量的一种非常缓慢的方式.最好创建主机向量,初始化它们,然后将它们复制到设备中.作为测试,修改你的代码(在你初始化设备向量X [i]和Y [i]的循环之后):

}  // this is your line of code
std::cout<< "Starting GPU run" <

然后,您将看到GPU计时结果几乎在添加的行打印出来之后立即出现.因此,您等待的所有时间都花在直接从主机代码初始化这些设备向量上.

当我在笔记本电脑上运行时,我得到的CPU时间大约为40,GPU时间大约为5,因此对于实际计时的代码段,GPU运行速度比CPU快8倍.

如果创建X和Y作为主机向量,然后创建类似的d_X和d_Y设备向量,则总体执行时间将更短,如下所示:

thrust::host_vector X(N);     
thrust::host_vector Y(N);     
thrust::device_vector Z(N);     
for(int i=0;i d_X = X;
thrust::device_vector d_Y = Y;

并将转换调用更改为:

thrust::transform(d_X.begin(), d_X.end(),      
    d_Y.begin(),      
    Z.begin(),      
    thrust::plus()); 

好的,所以你现在已经表明CPU运行测量比GPU测量快.对不起,我跳到了结论.我的笔记本电脑是惠普笔记本电脑,配备2.6GHz核心i7和Quadro 1000M gpu.我正在运行centos 6.2 linux.一些评论:如果您在GPU上运行任何繁重的显示任务,可能会降低性能.此外,在对这些事情进行基准测试时,通常的做法是使用相同的机制进行比较,如果需要,可以将cudaEvents用于两者,它可以将CPU代码的时间与GPU代码相同.此外,它与推力做热身跑就是不定时的通行做法,然后重复测试测量,同样是常见的做法来运行测试在一个循环10次以上,然后除以获得一个平均水平.在我的情况下,我可以告诉clock()测量是非常粗糙的,因为连续运行将给我30,40或50.在GPU测量我得到像5.18256.其中一些可能有所帮助,但我不能确切地说为什么你的结果和我的结果差别很大(在GPU方面).

好的我做了另一个实验.编译器将在CPU方面产生很大的不同.我用-O3开关编译和CPU时间下降到0.然后我转换CPU定时测量从时钟()方法来cudaEvents,和我的12.4(与-O3优化)和GPU仍然5.1 CPU测量的时间侧.

您的里程将根据计时方法和您在CPU端使用的编译器而有所不同.

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有