gpt4 book ai didi

c++ - OpenCL 的意外 CPU 使用率

转载 作者:太空宇宙 更新时间:2023-11-04 12:12:16 25 4
gpt4 key购买 nike

我编写了一个简单的 OpenCL 内核来计算 GPU 上两个图像的互相关。但是,当我使用 enqueueNDRangeKernel 执行内核时,一个内核的 CPU 使用率上升到 100%,但主机代码除了等待入队命令完成外什么都不做。这是 OpenCL 程序的正常行为吗?那里发生了什么?

OpenCL 内核(如果相关):

kernel void cross_correlation(global double *f,
global double *g,
global double *res) {
// This work item will compute the cross-correlation value for pixel w
const int2 w = (int2)(get_global_id(0), get_global_id(1));

// Main loop
int xy_index = 0;
int xy_plus_w_index = w.x + w.y * X;

double integral = 0;
for ( int y = 0; y + w.y < Y; ++y ) {
for ( int x = 0; x + w.x < X; ++x, ++xy_index, ++xy_plus_w_index ) {
// xy_index is equal to x + y * X
// xy_plus_w_index is equal to (x + w.x) + (y + w.y) * X
integral += f[xy_index] * g[xy_plus_w_index];
}

xy_index += w.x;
xy_plus_w_index += w.x;
}

res[w.x + w.y * X] = integral;
}

图像 f、g、res 的大小为 XY 像素,其中 XY 在编译时设置。我正在使用 X = 2048Y = 2048 测试上述内核。

附加信息:我在带有 OpenCL 1.2 版的 Nvidia GPU 上运行内核。 C++ 程序使用 OpenCL C++ Wrapper API 编写,并使用 bumblebee 包中的 optirun 在 Debian 上执行。

根据要求,这是一个最小的工作示例:

#include <CL/cl.hpp>

#include <sstream>
#include <fstream>

using namespace std;

int main ( int argc, char **argv ) {
const int X = 2048;
const int Y = 2048;

// Create context
cl::Context context ( CL_DEVICE_TYPE_GPU );

// Read kernel from file
ifstream kernel_file ( "cross_correlation.cl" );
stringstream buffer;
buffer << kernel_file.rdbuf ( );
string kernel_code = buffer.str ( );

// Build kernel
cl::Program::Sources sources;
sources.push_back ( { kernel_code.c_str ( ), kernel_code.length ( ) } );
cl::Program program ( context, sources );
program.build ( " -DX=2048 -DY=2048" );

// Allocate buffer memory
cl::Buffer fbuf ( context, CL_MEM_READ_WRITE, X * Y * sizeof(double) );
cl::Buffer gbuf ( context, CL_MEM_READ_WRITE, X * Y * sizeof(double) );
cl::Buffer resbuf ( context, CL_MEM_WRITE_ONLY, X * Y * sizeof(double) );

// Create command queue
cl::CommandQueue queue ( context );

// Create kernel
cl::Kernel kernel ( program, "cross_correlation" );

kernel.setArg ( 0, fbuf );
kernel.setArg ( 1, gbuf );
kernel.setArg ( 2, resbuf );

// Set input arguments
double *f = new double[X*Y];
double *g = new double[X*Y];

for ( int i = 0; i < X * Y; i++ )
f[i] = g[i] = 0.001 * i;

queue.enqueueWriteBuffer ( fbuf, CL_TRUE, 0, X * Y * sizeof(double), f );
queue.enqueueWriteBuffer ( gbuf, CL_TRUE, 0, X * Y * sizeof(double), g );

// Execute kernel
queue.enqueueNDRangeKernel ( kernel, cl::NullRange, cl::NDRange ( X, Y ), cl::NullRange, NULL, NULL );
queue.finish ( );

return 0;
}

最佳答案

您没有说您如何调用 enqueueNDRangeKernel - 这是关键位。据我了解,对于 NVidia,调用是阻塞的(尽管我不认为它应该是标准的一部分。)您可以通过让一个单独的线程调用 enqueueNDRangeKernel 并让该线程阻塞它而其他线程继续运行来解决这个问题,阻塞线程可以在它完成时发出事件信号。

有人讨论了here - 并且它提出了一些关于并行发生对入队的多个调用的警告。

关于c++ - OpenCL 的意外 CPU 使用率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48525489/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com