OpenCL на MacOS: SIGABRT в сборке выпуска, EXC_BAD_INSTRUCTION в libdispatch в сборке отладки при использовании AMD Radeon 555 в качестве устройства CL - PullRequest
0 голосов
/ 12 апреля 2019

Я сталкиваюсь с трудной для отслеживания ошибкой в ​​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, которые могли бы вызвать подобные ошибки?
...