OpenCL:将两个字符串传递给内核,return 什么都没有

OpenCL : pass two String to kernel, return nothing

我想将两个字符串传递给 OpenCL kernet,并直接从中打印文本。

到目前为止,我有这个:

int main(void) {
    Context(CL_DEVICE_TYPE_GPU);
    static const unsigned elements = 1000;

    vector<string> dataA;
    for (int i = 0; i < elements; i++) {
        dataA.push_back("a");
    }

    vector<string> dataB;
    for (int i = 0; i < elements; i++) {
        dataB.push_back("b");
    }

    Buffer a(begin(dataA), end(dataA), true, false);
    Buffer b(begin(dataB), end(dataB), true, false);

    Program addProg(R"d(
        kernel
        void add(string a, string b) {
            unsigned idx = get_global_id(0);
            c[idx] = 2.0;
        }
    )d", true);

    auto add = make_kernel<Buffer, Buffer>(addProg, "add");
    add(EnqueueArgs(elements), a, b);


    system("pause");
}

这段代码在没有解释的情况下在运行时崩溃。

我该如何调试它,是否可以从内核打印文本并将其显示在屏幕上?

好的,听起来您想要将 array/vector 字符串传递给内核,并让内核中的每个工作项处理一个不同的字符串。你不能用 STL 向量和字符串 类 真正做到这一点,因为它们在 OpenCL 内核中不起作用,所以最简单的方法是使用扁平的 C 字符数组(所有一个数组中的字符串)。

我已经修改了下面的程序来执行此操作。基本上,我们在 charsPerString 变量中设置任何字符串所需的最大字符数(假设您知道这是什么)。然后我们分配一个包含 elements*charsPerString 个字符的数组,并像您一样用单个字符初始化字符串。第 i 个字符串从索引 i*charsPerString 开始。然后我们可以将其作为单个缓冲区传递给内核。

内核然后让每个工作项打印出使用 printf 传递的两个字符串中的每一个的第一个字符,以与上述相同的方式计算其字符串的开头。

我还添加了带有异常的典型 C++ 错误检查方法,它将显示可能发生的任何 OpenCL 错误。我已经在我自己的笔记本电脑上测试过了,它可以工作,打印出来:

0 has characters a and b
1 has characters a and b
2 has characters a and b
3 has characters a and b
4 has characters a and b

(这是我们所期望的)。

希望您能够将其扩展到您自己的用例中。

#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <iostream>

using namespace cl;
using namespace std;

int main(void) {
  try {
    Context(CL_DEVICE_TYPE_GPU);
    static const unsigned elements = 1000;

    static const unsigned charsPerString = 16;

    char *dataA = new char[elements*charsPerString];
    for (int i = 0; i < elements; i++) {
      dataA[i*charsPerString] = 'a';
    }

    char *dataB = new char[elements*charsPerString];
    for (int i = 0; i < elements; i++) {
      dataB[i*charsPerString] = 'b';
    }

    Buffer a(dataA, dataA+elements*charsPerString, true, false);
    Buffer b(dataB, dataB+elements*charsPerString, true, false);

    Program addProg(R"d(
        constant unsigned charsPerString = 16;
        kernel
        void add(global char *a, global char *b) {
            unsigned idx = get_global_id(0);
            printf("%d has characters %c and %c\n",
                   idx, a[idx*charsPerString], b[idx*charsPerString]);
        }
    )d");

    try {
      addProg.build();
    }
    catch (Error err) {
      if (err.err() == CL_BUILD_PROGRAM_FAILURE) {
        cout << "OpenCL build failure:" << endl;
        cout << addProg.getBuildInfo<CL_PROGRAM_BUILD_LOG>(Device::getDefault());
      }
      throw err;
    }

    addProg.build();

    auto add = make_kernel<Buffer, Buffer>(addProg, "add");
    add(EnqueueArgs(elements), a, b);
    CommandQueue::getDefault().finish();

    delete[] dataA;
    delete[] dataB;
  }
  catch (Error err) {
    cerr << "ERROR: " << err.what() << " (" << err.err() << ")" << endl;
  }

  system("pause");
}