Время ядра OpenCL измеряет 0 секунд или вызывает SIGABRT - PullRequest
0 голосов
/ 06 января 2020

У меня проблемы с измерением времени простого ядра OpenCL на Arch Linux (Манджаро). Средства OpenCL для измерения времени дают мне время 0 секунд или дают ошибку в зависимости от условий.

Моя проблема

При выполнении промежуточного ядра (в основном out[i] = in[i];) на большом NDRange ЦПУ измеряет правильное время выполнения, а OpenCL сообщает 0. Вот вывод консоли:

CPU: 1.27449 s
GPU: 0 s

passthrough. cpp (выдержки)

#include <CL/cl2.hpp>
#include "../Timer.hpp"

// start timer
Timer t;

// enqueue blocking
cl::Event processingEvent;
cl_int err = device->_queue.enqueueNDRangeKernel(
        passthrough, // kernel
        cl::NullRange, // offset
        cl::NDRange(bufferSize), // global range
        {}, // local range
        nullptr, // wait for events
        &processingEvent // processing event
);
processingEvent.wait();

// measure time
double cpuUsec = t.deltaUsec();
double gpuUsec = Timer::deltaUsec(processingEvent);

// debug
cout << "CPU: " << cpuUsec / 1000000.0 << " s\n";
cout << "GPU: " << gpuUsec / 1000000.0 << " s\n";

Таймер. cpp (выдержки)

#include <chrono>
#include <ratio>
#include <CL/cl2.hpp>

Timer::Timer() {
    from = high_resolution_clock::now();
}

double Timer::deltaUsec() {
    return duration_cast<duration<double, std::ratio<1, 1000000>>>(high_resolution_clock::now() - from).count();
}

double Timer::deltaUsec(const cl::Event &event) {
    return (double) Timer::deltaNsec(event) / 1000.0;
}

// main function for the timing
unsigned long Timer::deltaNsec(const cl::Event &event) {
    auto end = event.getProfilingInfo<CL_PROFILING_COMMAND_END>();
    auto start = event.getProfilingInfo<CL_PROFILING_COMMAND_START>();
    return end - start;
}

Что я пробовал

  1. Я дважды проверил входные значения, чтобы они были равны выводу - так ядро ​​фактически работает.
  2. Я деактивировал оптимизацию компилятора - на тот случай, если они заставят GPU использовать то же самое буфер для входных и выходных значений.
  3. Я добавил несколько логи c, поэтому для выполнения кода остро требуется больше времени.
  4. Я проверил в LLDB start и end переменные в Timer::deltaNsec() не равны 0. Они не увеличиваются и увеличиваются каждый раз, когда я проверяю.
  5. После добавления #define CL_HPP_ENABLE_EXCEPTIONS перед e #import cl2.hpp Я получил следующую ошибку SIGABRT:
terminate called after throwing an instance of 'cl::Error'
  what():  clGetEventProfileInfo

LLDB намекнул мне на строку auto end = event.getProfilingInfo<CL_PROFILING_COMMAND_END>(); в Timer.cpp, что, я думаю, действительно сбивает с толку.

Согласно на этот ответ Я правильно использовал таймер - не так ли?


Дополнительная информация о моей системе / среде

Использован драйвер OpenCL (выдержки из пользовательского YAML):

    NVIDIA CUDA:
      Vendor: NVIDIA Corporation
      Version: OpenCL 1.2 CUDA 10.1.120
      Devices:
        GeForce GTX 1080 Ti:
          Timer resolution (ns): 1000
          Vendor: NVIDIA Corporation
          Version: OpenCL 1.2 CUDA
          Driver: 430.64

Установленные пакеты

lib32-opencl-nvidia 1:430.40-1
opencl-headers 2:2.2.20170516-2

Возможно, у кого-то возникла подобная проблема, и она может помочь.

... и Я надеюсь, что предоставил достаточно информации - если нет, пожалуйста, спросите!

1 Ответ

0 голосов
/ 06 января 2020

Ответ Алана Биртла помог мне найти проблему:

Я окружил ошибочный код блоком try-catch и напечатал код ошибки, который оказался -7: CL_PROFILING_INFO_NOT_AVAILABLE.

Чтобы иметь возможность измерять время выполнения, вам нужно включить профилирование на CommandQueue следующим образом:

auto queue = cl::CommandQueue(
        context,
        device,
        CL_QUEUE_PROFILING_ENABLE
);

Спасибо Алан !

...