将多个设备传递到上下文是否意味着内核将分发到两个设备?

Does passing multiple devices to a context, mean kernels will be distributed to both devices?

我一直在编写一些基本的 OpenCL 程序,并 运行将它们安装在一台设备上。我一直在对代码的性能进行计时,以了解每个程序的性能。

我一直在考虑让我的内核同时在平台 GPU 设备和 CPU 设备上 运行。 cl::context 构造函数可以传递 std::vector 设备,以初始化具有多个设备的上下文。我的系统只有一个 GPU 和一个 CPU.

要将内核分发到多个设备,您只需构建一个包含可用设备向量的上下文吗?当我用 2 个设备构建上下文时,我注意到性能显着提高,但它似乎太简单了。

有一个 DeviceCommandQueue 对象,也许我应该使用它来明确地为每个设备创建一个队列?

我在我的系统上做了一些测试。事实上,你可以这样做:

using namespace cl;
Context context({ devices[0], devices[1] });
queue = CommandQueue(context); // queue to push commands for the device, however do not specify which device, just hand over the context
Program::Sources source;
string kernel_code = get_opencl_code();
source.push_back({ kernel_code.c_str(), kernel_code.length() });
Program program(context, source);
program.build("-cl-fast-relaxed-math -w");

我发现如果这两个设备来自不同的平台(比如一个 Nvidia GPU 和一个 Intel GPU),clCreateContext 将在 运行 时间或 [=12] 抛出读取访问冲突错误=] 将在 运行 时失败。但是,如果这两个设备来自同一平台,则代码将编译并运行;但它不会 运行 在两个设备上。我使用 Intel i7-8700K CPU 及其集成的 Intel UHD 630 GPU 进行了测试,无论创建 context 的向量中的设备顺序如何,代码将始终在CPU 在这种情况下。我检查了 Windows Task-Manager 以及内核执行时间测量的结果(每个设备的执行时间都是特定的)。

您还可以使用任务管理器等工具监控设备使用情况,以查看哪个设备实际上正在 运行ning。如果您的系统与我观察到的有任何不同,请告诉我。

一般来说,跨多个设备的并行化 不是 通过将上下文传递给设备向量来完成的,而是给每个设备一个专用的 contextqueue 并明确处理在哪个队列上执行哪些内核。这使您可以完全控制内存传输和执行顺序/同步点。

我看到传入设备向量时性能有所提高。我下载了一个 CPU/GPU 分析器来实际检查我的 GPU 的 activity 和 CPU 当我是 运行 代码时我似乎看到 activity两种设备。 CPU 注册了大约 95-100% activity,GPU 达到了 30-40%,因此 OpenCL 必须在两个设备之间拆分内核。我的电脑有一个 CPU 和一个集成的 GPU,这可能在为什么内核在设备之间共享方面发挥了作用,因为它不像它有一个 CPU 和一个完全独立的 GPU,他们'在同一组件上重新连接。