2015-01-09 4 views
0

Я бы хотел передать две строки в ядро ​​OpenCL и напечатать текст непосредственно из него.OpenCL: передать две строки в ядро, не возвращать ничего

До сих пор, у меня есть это:

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"); 
} 

Этот код сбой во время выполнения без объяснения причин.

Как я могу отладить это, и можно ли печатать текст с помощью ядра и отображать его на экране?

+0

С какой платформой вы используете OpenCL? Можете ли вы показать код ядра? Вы пытались поймать любые исключения, брошенные из привязок OpenCL C++, чтобы получить полезное сообщение об ошибке? – jprice

+1

Согласен с jprice. Кроме того, на ваш вопрос: единственный возможный способ печати данных в строку из CL - использование расширений (например: cl_amd_printf) – DarkZeros

+0

Я использую версию OpenCL в комплекте с AMD SDK. Ядро находится в коде, я связал строку, начинающуюся с Program addPr ... Я не могу получить никакого исключения, кажется, что они не выбрасываются или что-то в этом роде, я просто получаю это окно http: //i.imgur .com/Vhj9uUD.png – Rogue

ответ

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"); 
} 
+0

Это потрясающе, именно так я и ожидал. Спасибо ;) – Rogue

Смежные вопросы