Greatings,
При использовании OpenCL я столкнулся со странным поведением.
main.cpp:
...
Future* future;
for(int k = 0; k < NUMITERATIONS; k++){
future = execute(arguments);
while(!future->isReady()){
cout << future->isReady() << "\n";
Sleep(500);
}
// get the data
...
// ouput results
...
// free resources
...
}
Предыдущий код выполняется хостом и цикломзаключается в том, чтобы гарантировать, что он продвигается только после того, как данные готовы.
код выполнения:
IFuture* execute(Argument* arguments[]){
//inicialize OpenCL data
...
//execute kernel on an a platform wrapper(mine)
cl_event event = exec->execute(inputBuffers,outputBuffers);
void** outputData = (void**) malloc(sizeof(void*)*numOutputEntries);
IFuture* future = new Future();
//prepare a struct for callback
callbackArgs* args = (callbackArgs*) malloc(sizeof(callbackArgs));
args->outputBuffers = outputBuffers;
args->inputBuffers = inputBuffers;
args->future = future;
args->numOutputEntries = numOutputEntries;
args->numInputEntries = numInputEntries;
args->outputMemSizes = outputMemSizes;
args->outputData = outputData;
args->queue = queue;
args->parser = parser;
//set callback
errcode = clSetEventCallback (event, CL_COMPLETE, &execComplete, args);
//free resources
...
return future;
}
Этот метод ставит в очередь выполнение и готовит функцию обратного вызова.Поскольку функция this является функцией-членом объекта, она должна быть объявлена статической для OpenCL, чтобы принять ее в качестве функции обратного вызова.Поэтому для передачи ему данных нестатического члена я создаю структуру, заполненную указателем на необходимые данные, и передаю указатель на эту структуру в функцию API OpenCL.
обратный вызов завершения выполнения:
void CL_CALLBACK execComplete(cl_event ev, cl_int event_status, void* user_data){
int i, errcode = 0;
callbackArgs* args = (callbackArgs*) user_data;
cl_event event;
// read data from device memory
for(...){
...
if(last enqueue)
errcode = clEnqueueReadBuffer(args->queue, args->outputBuffers[i], CL_FALSE, 0, someSize, args->outputData[i], 0, NULL, &event);
else
errcode = clEnqueueReadBuffer(args->queue, args->outputBuffers[i], CL_FALSE, 0, someSize, args->outputData[i], 0, NULL, NULL);
}
errcode = clSetEventCallback(event, CL_COMPLETE, &readComplete, user_data);
clFlush(args->queue);
}
Эта функция ставит в очередь асинхронные чтения из памяти.Эти чтения взаимодействуют с данными внутри структуры.Затем команды сбрасываются и регистрируется новый обратный вызов.
устанавливает обратный вызов результатов:
void CL_CALLBACK readComplete(cl_event ev, cl_int event_status, void* user_data){
callbackArgs* args = (callbackArgs*) user_data;
args->future->setData(args->outputData);
// release resources
...
}
Этот обратный вызов просто делает доступными данные.Функция future-> setData переводит будущий объект в состояние готовности, поэтому исходный активный цикл ожидания будет продолжен.Однако ценности, которые исполняют сторонние свидетели, никогда не меняются.
Я распечатал значения внутри и снаружи последней функции обратного вызова, и адрес объекта Future везде одинаков.Но его значения изменяются только внутри обратного вызова readComplete, приводя цикл в бесконечное состояние.
Надеюсь, я прояснил свою проблему.Заранее спасибо за ваши ответы.