代码之家  ›  专栏  ›  技术社区  ›  matdumsa

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

  •  11
  • matdumsa  · 技术社区  · 16 年前

    当我为一个多核编程类编写完我的项目时,我想到了一些非常奇怪的事情,我想和你讨论一下。

    我们被要求创建任何一个程序,它将在为多核平台编程方面显示出显著的改进。我决定尝试在GPU上编写一些代码来尝试OpenCL。我选择了矩阵卷积问题,因为我很熟悉它(我以前用开放MPI并行它,对大图像有很大的加速)。

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

    然后我运行我刚刚在我的MBP集成Geforce 9400上写的新OpenCL版本,平均时间为1.26秒。到目前为止还不错,它是12倍的加速!!

    但现在我进入我的节能面板,打开图形性能模式,该模式关闭Geforce 9400米,并打开Geforce 9600米燃气轮机我的系统。苹果公司说这张卡的速度是集成卡的两倍。

    你猜怎么着,我使用Kick Ass图形卡的时间平均是3.2秒,我的9600米燃气轮机似乎比9400米慢了两倍多。

    对于那些倾向于opencl的用户,我在启动之前将所有数据复制到远程缓冲区,因此实际的计算不需要往返于主RAM。此外,我还让OpenCL确定最佳的本地工作大小,因为我了解到它们在计算出参数方面做了非常好的实现。

    有人有线索吗?

    编辑:此处包含makefiles的完整源代码 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
    
    5 回复  |  直到 15 年前
        1
  •  10
  •   Umar Arshad    15 年前

    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);
    

    这个例子使用C++包装器,但是概念应该是相同的。

    希望这有帮助。

        2
  •  2
  •   Benjamin Horstman    16 年前

    我得到了同样的结果,我不确定为什么。我的内核只需要极少的复制操作(我为所有内核调用预置了所有需要的数据,只返回512x512映像)。它是一个光线跟踪器,所以内核的工作远远超过了拷贝(400+ms到10 ms)。不过,9600米燃气轮机的速度要慢1.5倍到2倍。

    根据Nvidia的列表,9600米燃气轮机应该有32个SP(是9400米燃气轮机的两倍)。估计它的时钟也更高了。

    9600米燃气轮机在某些情况下似乎更快,例如游戏。查看以下链接: http://www.videocardbenchmark.net/video_lookup.php?cpu=GeForce+9600M+GT http://www.videocardbenchmark.net/video\u lookup.php?cpu=geforce+9600m+gt

    根据 ars technica :

    此外,关于雪豹的实现的一个有趣的小消息被早期的测试所揭示。虽然Snow Leopard似乎无法为使用Nvidia Geforce 9400M芯片组的机器启用双GPU或动态GPU切换,但Leopardit带来的限制似乎表明,操作系统可以同时将两者用作OpenCL资源。因此,即使您的MacBook Pro上启用了9600M GT,如果在应用程序中遇到opencl代码,Snow Leopard也可以将该代码发送给在9400M中处于休眠状态的16个GPU内核进行处理。相反,当运行只有9400M的MacBook Pro时,情况并非如此。启用后,9600M GT将完全关闭以节省电力,并且不能用作OpenCL资源。

    这似乎与我们看到的相反。另外,我一次只在一个设备上显式地设置一个cl上下文。

    有一些建议 ars forums 9600米燃气轮机也不支持双打,这就解释了这个问题。我可能会尝试写一个合成的基准来测试这个假设。

        3
  •  1
  •   Kendall Hopkins    16 年前

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

    此外,我发现这个站点在我的OpenCL体验中非常有用。

    http://www.macresearch.org/opencl

        4
  •  1
  •   Bahbar    16 年前

    性能并不是Geforce 9400米和Geforce 9600米燃气轮机的唯一区别。一个大的是那个是一个 离散的 GPU。由此产生了一系列差异,其中以下因素可能会产生影响:

    • 驾驶员倾向于批处理更多命令
    • 记忆不统一。GPU通常只访问自己的内存,驱动程序通过PCI-E总线来回移动内存。

    我肯定我错过了一些…

    您可以尝试以下几种方法:

    • 避免调用clfinish。您在内存加载和执行之间调用它的方式强制驱动程序做比需要更多的工作。它使GPU暂停。
    • 分析您的代码以查看 什么 正在慢慢来。我还不知道对cl性能分析的支持,但是对于clfinish调用,它通过简单地测量CPU端给出了一阶估计。请注意,通常很难区分什么是延迟造成的,什么是吞吐量造成的。
        5
  •  0
  •   emchristiansen    15 年前

    我对Opencl不熟悉,所以我可能有点幼稚,但我怀疑你是否需要进入节能面板来切换Opencl计算设备。我相信在您的代码中设置OpenCL上下文时,您可以选择设备。

    我的假设是:1)当您在不首先禁用集成GPU的情况下运行代码时,OpenCL选择离散的GPU作为计算设备。您的代码运行在(快速)离散GPU上。2)当您首先禁用集成的GPU时,您强制将OS X GUI运行到离散卡上。当您运行代码时,它在离散的GPU上运行,但它与您的GUI争夺资源。

    这个答案将在被问到这个问题11个月后给出,但希望它对某人有用…

    推荐文章