OpenCL:将两个String传递给内核,什么都不返回

时间:2015-01-09 13:32:48

标签: c++ opencl

我想将两个String传递给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");
}

此代码在运行时崩溃,没有任何解释。

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

1 个答案:

答案 0 :(得分:2)

好的,所以听起来你想将一个数组/字符串向量传递给内核,并让内核中的每个工作项处理一个不同的字符串。你无法用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");
}