在CPU上使用OpenCL将一个数组复制到另一个数组要比C+慢得多+;代码 我比较了在CPU上运行的OpenCL代码的性能,它只将数据从一个2D数组复制到另一个2D数组,而将其复制到纯C++代码中。我在OpenCL代码中使用了一个工作组来进行公平的比较。我使用了英特尔的OpenCL驱动程序和英特尔编译器。OpenCL代码的速度大约是CPU代码的5倍。编译器为复制循环提供以下消息: loop was transformed to memset or memcpy. 关于如何用C++代码实现OpenCL代码的速度的建议?< /P>

在CPU上使用OpenCL将一个数组复制到另一个数组要比C+慢得多+;代码 我比较了在CPU上运行的OpenCL代码的性能,它只将数据从一个2D数组复制到另一个2D数组,而将其复制到纯C++代码中。我在OpenCL代码中使用了一个工作组来进行公平的比较。我使用了英特尔的OpenCL驱动程序和英特尔编译器。OpenCL代码的速度大约是CPU代码的5倍。编译器为复制循环提供以下消息: loop was transformed to memset or memcpy. 关于如何用C++代码实现OpenCL代码的速度的建议?< /P>,c++,arrays,performance,opencl,C++,Arrays,Performance,Opencl,谢谢 OpenCL主机代码: #include <cstdio> #include <cstdlib> #include <iostream> #include <fstream> #include <cmath> #include <ctime> #include <CL/cl.hpp> int main(int argc, char **argv) { // Create the two input

谢谢

OpenCL主机代码:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <cmath>
#include <ctime>
#include <CL/cl.hpp>

int main(int argc, char **argv)
{
    // Create the two input vectors
    const int N = 8192;
    double *in = new double[N*N]; 
    double *out = new double[N*N];

    for(int i = 0; i < N; i++)
        for (int j=0; j < N; j++) {
            in[i*N + j] = i + j;
            out[i*N + j] = 0.;
    }


    double time;
    std::clock_t start;
    int niter = 100;

    cl_int cl_err;

    std::vector<cl::Platform> platforms;
    cl_err = cl::Platform::get(&platforms);

    std::vector<cl::Device> devices;
    cl_err = platforms.at(1).getDevices(CL_DEVICE_TYPE_CPU,
                                        &devices);

    cl_context_properties context_properties[3] = {CL_CONTEXT_PLATFORM,
                                    (cl_context_properties)(platforms.at(1)()),
                                                   0};
    cl::Context context = cl::Context(devices, 
                                      context_properties, 
                                      NULL, NULL, &cl_err);

    cl::Buffer buffer_in = cl::Buffer(context, 
                                      CL_MEM_USE_HOST_PTR | CL_MEM_READ_ONLY,
                                      N*N*sizeof(double), 
                                      in, &cl_err);

    cl::Buffer buffer_out = cl::Buffer(context, 
                                       CL_MEM_USE_HOST_PTR | CL_MEM_WRITE_ONLY, 
                                       N*N*sizeof(double),
                                       out, &cl_err);

    cl::CommandQueue queue = cl::CommandQueue(context, devices.at(0), 0, &cl_err);

    std::ifstream sourceFile("vector_copy.cl");
    std::string sourceCode((std::istreambuf_iterator<char>(sourceFile)),
                            std::istreambuf_iterator<char>());
    cl::Program::Sources source(1, std::make_pair(sourceCode.c_str(),
                                sourceCode.length()+1));

    cl::Program program(context, source, &cl_err);

    cl_err = program.build(devices, NULL, NULL, NULL);

    cl::Kernel kernel(program, "vector_copy", &cl_err);

    cl_err = kernel.setArg(0, buffer_in); 
    cl_err = kernel.setArg(1, buffer_out);
    cl_err = kernel.setArg(2, N);

    cl::NDRange global(N);
    cl::NDRange local(N);

    start = std::clock();
    for (int n=0; n < niter; n++) {
        cl_err = queue.enqueueNDRangeKernel(kernel,
                                            cl::NullRange,
                                            global,
                                            local,
                                            NULL, NULL);

        cl_err = queue.finish();
    }

    time =  (std::clock() - start)/(double)CLOCKS_PER_SEC;
    std::cout << "Time/iteration OpenCL (s) = " << time/(double)niter << std::endl;

    return(0);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv)
{
//创建两个输入向量
常数int N=8192;
双精度*in=新双精度[N*N];
double*out=新的double[N*N];
对于(int i=0;iSTD::OUTCL:OpenCL代码,即使优化,它仍然执行拷贝1BY1(工作项按工作项)。因为OpenCL编译器只允许按每个工作项优化。而C++的情况将被编译器优化为<代码> MycPy.()/Cube >调用(可能是编译器告诉你的)。
如果禁用编译器优化,它将在GPU中执行得更快


btw是否有这个原因?C++中有<代码> MycPy](<)>代码> <强> >代码> CeleQueReopopBuffor()
在OpenCL中为此目的。我认为后一个是您应该使用的。

英特尔OpenCL编译器能够跨工作组进行矢量化。基本上,一个函数在不同的SSE寄存器中同时运行8个线程

您的特定内核不能做到这一点。但这并不重要。我使用Visual Studio 2010和最新的Intel OpenCL for applications测试了您的程序。我被迫将N从8192减少到4096,因为我使用的集成GPU将OpenCL缓冲区的最大大小减少到128MB,即使只使用了CPU

我的结果是:你的OpenCL内核给了我大约6956MB/s的带宽。一个变化很小的内核(它被称为N*N作为全局大小,NULL作为本地大小,因为如果我们根本不关心本地内存,那么对于CPU,我们应该不定义它)

给出了大致相同的结果(7006MB/s)。该内核实际上是跨线程矢量化的,这可以通过“英特尔OpenCL内核编译器”进行验证。它为一个多线程生成一个内核(如4个)然后它只运行向量化内核,直到它必须在最后几个工作项中运行单线程内核

< C++代码给出了64 94Mb/s,所以它是相当符合的。我认为ICC甚至不可能使它更快5X。 我注意到您的代码中有平台。在(1)中,您的计算机中的平台0是什么


请记住,如果您根本不关心本地内存(在内核中不调用get_local_id)您应该将EnQueNeRangReGE的本地大小视为一个简单的魔法参数。要么将其设为NULL,要么尝试找到一个产生最快结果的值。< /P>在这两种情况下,您都可以为循环提供反汇编吗?英特尔编译器能够在纯C++版本中重新配置嵌套循环结构,因此检查编译后的编译程序。二进制或找到一种方法来抑制它。在GPU上做矩阵计算是否涉及从CPU到CPU传输输入和输出的额外成本?我建议在C++中使用一些东西[OJ] = [j]=[j] * 2 +1;+ 1阻止编译。
__kernel void vector_copy(__global const double* restrict in, 
                          __global double* restrict out,
                         const int N) 
{

    int i = get_global_id(0);
    int j;

    for (j=0; j<N; j++) {
        out[j + N*i] = in[j + N*i];
    }

}
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <cmath>
#include <ctime>

const int N = 8192;

int main(int argc, char **argv)
{
    double *in = new double[N*N]; 
    double *out = new double[N*N];
    // Create the two input vectors
    for(int i = 0; i < N; i++)
        for (int j=0; j < N; j++) {
            in[j + N*i] = i + j;
            out[j + N*i] = 0.;
    }


    std::clock_t start;
    int niter = 100;

    start = std::clock();
    for (int n=0; n < niter; n++) {
        for (int i=0; i<N; i++)
            for (int j=0; j<N; j++) {
                out[j + N*i] = in[j + N*i];
            }

    }

    double time =  (std::clock() - start)/(double)CLOCKS_PER_SEC;
    std::cout << "Time/iteration C = " << time/(double)niter << std::endl;

    return(0);
}
__kernel void vector_copy2(__global const double* restrict in, 
                      __global double* restrict out) 
{
  int i = get_global_id(0);
  out[i] = in[i];
}