C++ gcc是否通过nvcc将这些总和和最大减少量矢量化?

C++ gcc是否通过nvcc将这些总和和最大减少量矢量化?,c++,vector,cuda,sum,max,C++,Vector,Cuda,Sum,Max,我有一个CUDA应用程序,目前使用推力库在GPU上对向量进行求和和和最大缩减。我发现对于某些向量长度,如果将向量发送回主机并计算C++中的和和max减少,则更快得多。 总和和最大减少量应可在主机上矢量化。主机上的内存是线性/连续的,我正在使用的编译器(GCC)支持它。考虑到我看到的计时,编译器似乎正在对代码进行矢量化,但我如何确认这一点?我没有任何强制编译器优化的经验,但我知道可以使用一些pragma语句。(通过谷歌搜索,你们会发现几乎并没有什么信息。)另外,我也不想通过挖掘汇编来确认,因为我不

我有一个CUDA应用程序,目前使用推力库在GPU上对向量进行求和和和最大缩减。我发现对于某些向量长度,如果将向量发送回主机并计算C++中的和和max减少,则更快得多。 总和和最大减少量应可在主机上矢量化。主机上的内存是线性/连续的,我正在使用的编译器(GCC)支持它。考虑到我看到的计时,编译器似乎正在对代码进行矢量化,但我如何确认这一点?我没有任何强制编译器优化的经验,但我知道可以使用一些pragma语句。(通过谷歌搜索,你们会发现几乎并没有什么信息。)另外,我也不想通过挖掘汇编来确认,因为我不会理解它。是否有一个编译器设置(在GCC或NVCC中),我可以使用它在主机上强制矢量化,或者找到代码正在矢量化的确认

我为求和和和最大约化编写的函数如下。nvcc编译器最终将编译此代码,因为函数包含CUDA代码

void calc_vector_max_host(double& maxval, double *const vec_h, const double *const vec_d, int len)
{
    //copy device vector to host
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost));

    //vectorized? max
    maxval = *vec_h;
    double* temp = vec_h;
    for(int i = 1; i < len; i++, temp++)
    {
        if(*temp > maxval)
        {
            maxval = *temp;
        }
    }
}

void calc_vector_sum_host(double& sum, double *const vec_h, const double *const vec_d, int len)
{
    //copy device vector to host
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost));

    //vectorized? sum
    sum = 0.0;
    double* temp = vec_h;
    for(int i = 0; i < len; i++, temp++)
    {
        sum += *temp;
    }
}
void calc_vector_max_host(double&maxval,double*const vec_h,const double*const vec_d,int len)
{
//将设备向量复制到主机
gpuErrchk(cudaMemcpy(vec_h,vec_d,len*sizeof(double),cudaMemcpyDeviceToHost));
//矢量化?最大值
maxval=*vec_h;
双*温度=vec_h;
对于(int i=1;i最大值)
{
maxval=*温度;
}
}
}
无效计算向量求和主机(双精度&求和,双精度*常量向量,常量双精度*常量向量,整数长度)
{
//将设备向量复制到主机
gpuErrchk(cudaMemcpy(vec_h,vec_d,len*sizeof(double),cudaMemcpyDeviceToHost));
//矢量化求和
总和=0.0;
双*温度=vec_h;
对于(int i=0;i
编辑:下面包含gcc自动矢量化所需的更正。注释中列出的编译器选项也是必需的

void calc_vector_max_host(double& maxval, double *const __restrict__ vec_h, const double *const __restrict__ vec_d, int len)
{
    //copy device vector to host
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost));

    //vectorized? max
    double local_maxval = vec_h[0];
    for(int i = 1; i < len; i++)
    {
        double val = vec_h[i];
        if(val > local_maxval)
        {
            local_maxval = val;
        }
    }
    maxval = local_maxval;
}

void calc_vector_sum_host(double& sum, double *const __restrict__ vec_h, const double *const vec_d, int len)
{
    //copy device vector to host
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost));

    //vectorized? sum
    double local_sum = 0.0;
    for(int i = 0; i < len; i++)
    {
        local_sum += vec_h[i];
    }
    sum = local_sum;
}
void calc_vector_max_host(双倍&maxval,双倍*常数_限制_向量,双倍*常数_限制_向量,整数长度)
{
//将设备向量复制到主机
gpuErrchk(cudaMemcpy(vec_h,vec_d,len*sizeof(double),cudaMemcpyDeviceToHost));
//矢量化?最大值
双局部_maxval=vec_h[0];
对于(int i=1;ilocal_maxval)
{
本地_maxval=val;
}
}
maxval=本地_maxval;
}
无效计算向量求和主机(双和,双常数限制,常数双常数向量,整数)
{
//将设备向量复制到主机
gpuErrchk(cudaMemcpy(vec_h,vec_d,len*sizeof(double),cudaMemcpyDeviceToHost));
//矢量化求和
双局部_和=0.0;
对于(int i=0;i
首先,也是最重要的一点是,nvcc不是编译器。它是一个编译器驱动程序——它只是使用主机编译器结合两个自定义预处理工具来指导编译,这些工具分解实际的GPU代码并将其传递给GPU工具链。GPU编译器和汇编程序只涉及典型程序的一小部分。构建的其余部分直接使用主机编译器和链接器完成

因此,您发布的所有代码都是由gcc编译的(可以不使用nvcc直接编译)。nvcc有一个选项
-Xcompiler
,可用于将任何选项传递给主机编译轨迹。对于矢量化,您可以传递您的gcc版本支持的任何选项。如果您愿意的话,还可以直接使用SSE风格的内部函数来简化编译器的工作

要查看主机代码中是否已经发生了矢量化,只需使用类似于objdump/otool的东西(取决于您使用的是Linux还是OSX,您没有说过)。您将能够查看编译器发出的代码的反汇编,矢量化指令的出现将立即回答您的问题


最后,nvcc最近的表现非常出色,这一点毫无价值。通过熟悉nvcc,您可以找到这个问题的答案,或许还可以找到关于nvcc的所有其他问题的答案。

一些评论,仅供记录。gcc选项网页的链接非常有用。最初发布的代码毕竟不是自动矢量化的。这是由于缺少一些编译器选项。具体地说,我必须使用-Xcompiler标志传递所有的-ftree vectorize-msse2和-ffast math来获得要向量化的代码,以及ftree vectorize verbose=6来获得自动向量化编译器输出。我正在使用Linux并尝试使用objdump,但没有发现程序集转储对解决此问题非常有用。这些功能也有一些问题,已经编辑过了。