Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何在多核上编译OpenCL程序?_Multithreading_Macos_Opencl - Fatal编程技术网

Multithreading 如何在多核上编译OpenCL程序?

Multithreading 如何在多核上编译OpenCL程序?,multithreading,macos,opencl,Multithreading,Macos,Opencl,OpenCL程序/内核在运行时使用clBuildProgram()函数生成/编译。我的程序动态地创建要构建的内核,因此需要花费大量的时间来编译它们。当然,鉴于有许多内核,并且它们彼此完全独立,我想将这项工作分为多个内核,如下面的代码片段所示: 似乎有一个非常类似的问题,但这是6年前,解决方案并不真正令人满意 ThreadPool tempPool=ThreadPool(); 自动启动=标准::时钟::稳定时钟::现在(); 对于(int reps=0;reps0){ 线程::睡眠(1); } 自

OpenCL程序/内核在运行时使用clBuildProgram()函数生成/编译。我的程序动态地创建要构建的内核,因此需要花费大量的时间来编译它们。当然,鉴于有许多内核,并且它们彼此完全独立,我想将这项工作分为多个内核,如下面的代码片段所示:

似乎有一个非常类似的问题,但这是6年前,解决方案并不真正令人满意

ThreadPool tempPool=ThreadPool();
自动启动=标准::时钟::稳定时钟::现在();
对于(int reps=0;reps<50;reps++){
tempPool.addJob([此](){
自动启动=标准::时钟::稳定时钟::现在();
//这些将保存程序源
std::vector sources={sourceCode.toRawUTF8()};
std::vector sourcelength={sourceCode.getNumbyteSautf8()};
cl_int ret;
cl_program program=clCreateProgramWithSource(getCLContext(),1,sources.data(),sourceLength.data(),&ret);
//构建程序
ret=clBuildProgram(程序,1,&getCLDevices()[0](),NULL,NULL,NULL);
如果(ret){
//一般错误检查
}
auto singleDuration=std::chrono::duration(std::chrono::stable_clock::now()-start).count();
});
}
//等待所有作业完成的简单方法
while(tempPool.getNumJobs()>0){
线程::睡眠(1);
}
自动调整时间=std::chrono::duration(std::chrono::staddy_clock::now()-start).count();
我使用这个线程池设置所做的每件事都会导致5-6个线程的加速(我有8个线程),这是意料之中的。然而,构建OpenCL内核并不是这样。似乎一次只能有一个内核构建

有解决办法吗?我使用MacOS atm,但我也对Linux/Windows感兴趣

如果没有,是否有一种方法可以构建不涉及clBuildProgram()的OpenCL内核,但例如gcc或类似的解决方案?

(我很惊讶,您平台的驱动程序还没有多线程。您确定调用是真的并行的。)

如果你仍然被困在这里,下面是一个可能对你的参考问题的解决方案起作用的糟糕的黑客。对于某些驱动程序,
clCreateProgramWithBinaries
的速度要快得多。因此,

  • fork新进程(或调用使用相同设备集的helper可执行文件)
  • 每个子进程调用
    clCreateProgramWithSource
    ,然后调用
    clBuildProgram
  • 子进程调用
    clGetProgramInfo(…CL\u PROGRAM\u BINARIES…)
    获取二进制文件,然后通过文件、管道或其他进程间通信将其传回

  • 再一次,我会在用管道胶带将此黑客连接在一起之前再次检查您的设置代码。

    Tbh对此我也感到惊讶。苹果似乎很久以前就放弃了OpenCL(它甚至在新版本中被弃用),所以这可能是原因之一。因此,我也很好奇Linux/Windows实现是否也遇到了同样的问题,但我无法测试atm。至少在我上次尝试时,Xcode实际上已经解决了处理OpenCL内核二进制文件的一些尴尬问题。这是不可移植到其他平台的,但听起来你似乎并不真正关心这一点。如果你只需要针对macOS 10.14和更新版本,只关心在GPU上运行,但是,我强烈建议切换到金属计算内核,因为它们得到了更好的支持。(macOS 10.14放弃了对不支持Metal的GPU的支持,因此使用OpenCL不会给您带来任何额外的兼容性)预编译支持对我没有帮助,因为所有内核都是在运行时基于(除其他外)用户输入动态创建的。关于金属,我也研究了这个选项,但不幸的是它不够atm(例如没有FP64支持)。OpenCL也让我可以选择在将来相对轻松地移植程序。
    ThreadPool tempPool = ThreadPool();
    auto start = std::chrono::steady_clock::now();
    
    for (int reps = 0; reps < 50; reps++) {
        tempPool.addJob([this] () {
            auto start = std::chrono::steady_clock::now();
    
            //These would hold the program sources
            std::vector<const char*> sources = {sourceCode.toRawUTF8()};
            std::vector<const size_t> sourceLengths = {sourceCode.getNumBytesAsUTF8()};
    
            cl_int ret;
            cl_program program = clCreateProgramWithSource(getCLContext()(), 1, sources.data(), sourceLengths.data(), &ret);
    
            // Build the program
            ret = clBuildProgram(program, 1, &getCLDevices()[0](), NULL, NULL, NULL);
            if (ret) {
                //Generic error checking
            }
    
            auto singleDuration = std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - start).count();
        });
    }
    
    //Simple way to wait for all jobs to be finished
    while (tempPool.getNumJobs() > 0) {
        Thread::sleep(1);
    }
    
     auto totaDuration = std::chrono::duration <double, std::milli> (std::chrono::steady_clock::now() - start).count();