Я сталкиваюсь с трудной для отслеживания ошибкой в MacOS в приложении на основе OpenCL. В сборке релиза мой код в какой-то момент вылетает с SIGABRT, в сборке релиза я получаю EXC_BAD_INSTRUCTION
в потоке, очевидно, управляющем некоторыми компонентами lib dispatch / GCD (com.apple.libdispatch-manager
). Обратите внимание, что я не называю никакие вещи, связанные с GCD, поэтому полагаю, что это выполняется средой Apple OpenCL в фоновом режиме.
Контекст представляет собой приложение для тестирования производительности, которое измеряет задержку между постановкой в очередь команд CL и получением обратного вызова CL_COMPLETE
для различных способов доступа к буферам CL. Вы найдете код ниже. Ошибка возникает только для одного из трех доступных устройств CL в моем MacBook Pro (AMD Radeon Pro 555 Compute Engine).
Соответствующая часть кода:
nlohmann::json performTestUseHostPtr()
{
nlohmann::json results;
std::vector<cl::Event> inputBufferEvent (1);
std::vector<cl::Event> outputBufferEvent (1);
std::vector<cl::Event> kernelEvent (1);
for (auto size : testSizes)
{
std::vector<float> inputBufferHost (size);
std::vector<float> outputBufferHost (size);
cl::Buffer inputBuffer (context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_ONLY, size * sizeof (float), inputBufferHost.data());
cl::Buffer outputBuffer (context, CL_MEM_USE_HOST_PTR | CL_MEM_WRITE_ONLY, size * sizeof (float), outputBufferHost.data());
void* inputBufferMapped = queue.enqueueMapBuffer (inputBuffer, CL_TRUE, CL_MAP_WRITE_INVALIDATE_REGION, 0, size * sizeof (float));
std::memcpy (inputBufferMapped, testData.data(), size * sizeof (float));
kernel.setArg (0, inputBuffer);
kernel.setArg (1, outputBuffer);
for (int i = 0; i < numTests; ++i)
{
startTimes[i] = my::HighResolutionTimer::now();
queue.enqueueUnmapMemObject (inputBuffer, inputBufferMapped, nullptr, &inputBufferEvent[0]);
inputBufferEvent[0].setCallback (CL_COMPLETE, setTimestampCallback, &unmapCompletedTimes[i]);
queue.enqueueNDRangeKernel (kernel, cl::NullRange, cl::NDRange (size), cl::NullRange, &inputBufferEvent, &kernelEvent[0]);
kernelEvent[0].setCallback (CL_COMPLETE, setTimestampCallback, &kernelCompletedTimes[i]);
void* outputBufferMapped = queue.enqueueMapBuffer (outputBuffer, CL_FALSE, CL_MAP_READ, 0, size * sizeof (float), &kernelEvent, &outputBufferEvent[0]);
outputBufferEvent[0].setCallback (CL_COMPLETE, setTimestampCallback, &mapCompletedTimes[i]);
inputBufferMapped = queue.enqueueMapBuffer (inputBuffer, CL_TRUE, CL_MAP_WRITE_INVALIDATE_REGION, 0, size * sizeof (float), &kernelEvent, nullptr);
// --- Release build error seems to happen somewhere here ---
queue.finish();
std::memcpy (inputBufferMapped, outputBufferMapped, size * sizeof (float));
queue.enqueueUnmapMemObject (outputBuffer, outputBufferMapped);
queue.finish();
}
queue.enqueueUnmapMemObject (inputBuffer, inputBufferMapped);
results["vecSize=" + std::to_string (size)] = calculateTimes();
queue.finish();
}
return results;
}
Примечания:
Я проверил коды ошибок всех вызовов CL, все возвращают CL_SUCCESS
, просто удалил их в приведенном выше коде для лучшего обзора.
Я пометил строку, где я приблизительно предполагаю, что ошибка произошла, это основано на вставке операторов print в release-версию и наблюдении, какие точки кода были завершены до возникновения ошибки. Более того, вставка оператора печати над оператором queue.finish();
позволяет этой ошибке исчезнуть, так что, вероятно, это связано с синхронизацией.
Обновление:
Вставляя короткий сон в строку, где я предположил, что ошибка произошла, и выполняя отладочную сборку, она теперь также запускает SIGABRT. Дополнительно я могу найти следующие отпечатки на консоли:
OpenCLLatencyTests(17903,0x10012a5c0) malloc: tiny_free_list_remove_ptr: Internal invariant broken (next ptr of prev): ptr=0x1003052d0, prev_next=0x0
OpenCLLatencyTests(17903,0x10012a5c0) malloc: *** set a breakpoint in malloc_error_break to debug
Signal: SIGABRT (signal SIGABRT)
E0412 11:55:02.898913 233472000 ProtobufClient.cpp:63] No such process
Вопрос:
- Может кто-нибудь заметить явную ошибку в моем коде?
- Если нет, есть ли какие-либо известные ошибки в реализации Apple OpenCL, которые могли бы вызвать подобные ошибки?