我的OpenCL内核在更快的硬件上速度较慢..但为什么呢?

mat*_*msa 11 opencl hardware-acceleration

在我完成多核编程课程的编写时,我想出了一些非常奇怪的东西,我想和你讨论.

我们被要求创建任何程序,以显示为多核平台编程的显着改进.我决定尝试在GPU上编写代码以试用OpenCL.我已经选择了矩阵卷积问题,因为我对它非常熟悉(我之前使用open_mpi对它进行了并行处理,对于大图像来说速度很快).

所以在这里,我选择一个大的GIF文件(2.5 MB)[2816X2112],我运行顺序版本(原始代码),我得到平均15.3秒.

然后我运行我刚刚在我的MBP集成GeForce 9400M上编写的新OpenCL版本,我得到的平均时间为1.26秒.到目前为止一切都很好,它的速度是12倍!

但是现在我进入节能面板打开"图形性能模式"该模式关闭GeForce 9400M并打开我的系统所具有的Geforce 9600M GT.Apple称这张卡的速度是集成卡的两倍.

猜猜看,我使用kick-ass显卡的时间平均为3.2秒...我的9600M GT似乎比9400M慢两倍多..

对于那些倾向于OpenCL的人,我在开始之前将所有数据复制到远程缓冲区,因此实际计算不需要往返于主ram的往返.另外,我让OpenCL确定最佳本地工作量,因为我已经读过它们在确定参数时已经做了很好的实现.

有人有线索吗?

编辑:makefile文件的完整源代码http://www.mathieusavard.info/convolution.zip

cd gimage
make
cd ../clconvolute
make
put a large input.gif in clconvolute and run it to see results
Run Code Online (Sandbox Code Playgroud)

Uma*_*had 10

9400M集成到您的内存控制器,而9600M GT是一个独立的卡,通过PCI-e总线连接到您的内存控制器.这意味着当您将内存传输到9400M时,它只需将其分配到系统RAM中.另一方面,9600M通过PCI-e将数据发送到卡上的专用图形内存.这种转移使您的基准显得更慢.

如果您想比较两个显卡的性能,您应该使用OpenCL分析功能,而不是您当前使用的时钟功能.

cl_int clGetEventProfilingInfo (cl_event event, cl_profiling_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)

将函数传递给您将内核排入队列时创建的事件,并将CL_PROFILING_COMMAND_START传递给第二个参数,以便以纳秒为单位获取内核的起始点,并将CL_PROFILING_COMMAND_END传递给内核的终点.确保在内核执行完成后使用此命令(事件保持其值超出范围.)您还可以通过将此函数应用于事件来获取将数据传输到设备所花费的时间.从缓冲区的入队.这是一个例子:

        TRACE("Invoking the Kernel")
    cl::vector<cl::Event> matMultiplyEvent;
    cl::NDRange gIndex(32,64);
    cl::NDRange lIndex(16,16);

    err = queueList["GPU"]->enqueueNDRangeKernel(
                                                 matrixMultiplicationKernel, 
                                                 NULL, 
                                                 gIndex, 
                                                 lIndex, 
                                                 &bufferEvent,
                                                 matMultiplyEvent);
    checkErr(err, "Invoke Kernel");


    TRACE("Reading device data into array");
    err = queueList["GPU"]->enqueueReadBuffer(thirdBuff, 
                                              CL_TRUE,
                                              0,
                                              (matSize)*sizeof(float),
                                              testC,
                                              &matMultiplyEvent,
                                              bufferEvent);
    checkErr(err, "Read Buffer");
    matMultiplyEvent[0].wait();
    for (int i = 0; i < matSize; i++) {
        if (i%64 == 0) {
            std::cout << "\n";
        }
        std::cout << testC[i] << "\t";
    }
    long transferBackStart = bufferEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_START>();
    long transferBackEnd = bufferEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_END>();
    double transferBackSeconds = 1.0e-9 * (double)(transferBackEnd- transferBackStart);

    long matrixStart = matMultiplyEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_START>();
    long matrixEnd = matMultiplyEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_END>();
    double dSeconds = 1.0e-9 * (double)(matrixEnd - matrixStart);
Run Code Online (Sandbox Code Playgroud)

此示例使用C++包装器,但概念应该相同.

希望这可以帮助.


Ken*_*ins 1

当我在 MacBook 上测试 OpenCL 时,我遇到了同样的问题。我相信这是因为 GeForce 9400M 到主内存组的总线速度比 Geforce 9600M GT 更高。因此,尽管 Geforce 9600M GT 的性能比 GeForce 9400M 强大得多,但将内存复制到 GPU 所需的时间太长,无法看出更强大的 GPU 对您的情况带来的好处。这也可能是由于工人组规模不适当造成的。

我还发现这个网站对我的 OpenCL 体验非常有帮助。

http://www.macresearch.org/opencl