#c #opencv #opencl
#c #opencv #opencl
Вопрос:
Окружающая среда:
- Intel i7-9750H
- Intel UHD Graphics 630
- Nvidia GTX1050 (ноутбук)
- Visual studio 2019 / C
- OpenCV 4.4
- OpenCL 3.0 (intel) / 1.2 (nvidia)
Я пытаюсь использовать OpenCL для ускорения моего кода. Но результат показывает, что процессор работает быстрее, чем графический процессор. Как я мог ускорить свой код?
void GetHoughLines(cv::Mat dst) {
cv::ocl::setUseOpenCL(true);
int img_w = dst.size().width; // 5000
int img_h = dst.size().height; // 4000
cv::UMat tmp_dst = dst.getUMat(cv::ACCESS_READ);
cv::UMat tmp_mat = cv::UMat(dst.size(), CV_8UC1, cv::Scalar(0));
for (size_t i = 0; i < 1000; i )
{
tmp_mat = tmp_mat.mul(tmp_dst);
}
}
Это заняло около 3000 мс, когда я использовал только CPU.
Когда я использовал Intel UHD Graphics 630, потребовалось 3500 мс.
И я также попробовал GTX1050, но это заняло около 3000 мс.
Пожалуйста, дайте мне несколько идей, чтобы ускорить его. Я должен сделать это не менее 1000 мс. Должен ли я использовать AMP или OpenMP? Но, как я знаю, они могут вычислять только простые операции, не подходящие для функций OpenCV.
Комментарии:
1. Вот почему называть это видеокартой действительно щедро. Встроенный графический процессор Intel, как известно, работает медленно, так как это минимальный минимум, который вы можете установить на чип, чтобы получить реальную графику на экране, не более того. Вы получите гораздо лучшие результаты на дискретном графическом процессоре. Карта AMD или NVidia среднего уровня, вероятно, будет работать значительно лучше.
2. @tadman Спасибо за ваш ответ. Как вы прокомментировали, я пытался использовать графический процессор Nvidia. Но он все еще медленный. У вас есть другие идеи для ускорения?
3. Получите более быстрый графический процессор. Рассмотрите возможность использования сервиса GPU-on-demand, например, облачного варианта, если вам просто нужно выполнить несколько быстрых запусков. Посмотрите на любые алгоритмические улучшения, которые вы можете внести. Используйте профилировщик, чтобы узнать, можно ли выполнить какие-либо оптимизации. Посмотрите, действительно ли вам нужно 1000 итераций. И т.д.
4. Я не знаю точно, как open cv реализовал open CL, но я полагаю, что ваша матрица должна копироваться в графический процессор и обратно для каждой итерации цикла, что будет неэффективно, написанный вручную open CL, вероятно, будет быстрее
5. Спасибо за совет @tadman, AlanBirtles, pmdj Я найду другие способы.
Ответ №1:
По сути, ваш код работает медленно, потому что способ, которым OpenCV использует OpenCL, неэффективен. Это не имеет ничего общего с базовым оборудованием.
Для того, чтобы код OpenCL (или любой код, связанный с GPU, если на то пошло) был эффективным, крайне важно, чтобы код на стороне хоста правильно использовал графический процессор. Назовем несколько принципов:
- Насыщайте графический процессор, асинхронно ставя в очередь множество вычислений (ядер).
- Избегайте ненужных синхронизаций.
- Избегайте ненужных копий памяти между хост-процессором и устройством GPU.
Даже если вы пишете наиболее оптимизированные ядра GPU, но не придерживаетесь этих основ, вы вряд ли получите какое-либо повышение производительности.
Кодовая база OpenCV — отличный пример того, как не следует придерживаться этих принципов.
Что касается вашего примера, если вы перепишете свой код, чтобы избежать копирования памяти и явно использовать память устройства, вы можете стать свидетелем разумной производительности:
auto frame1 = cv::UMat(size, format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
auto frame2 = cv::UMat(size, format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
auto frame3 = cv::UMat(size, format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
for (size_t i = 0; i < 10; i )
{
cv::multiply(frame1, frame2, frame3);
}
Но в любом случае я рекомендую вам научиться использовать OpenCL API без OpenCV.
Комментарии:
1. Это именно то, что я нашел. Архитектура OpenCV не способствует современной асинхронной работе, поэтому неудивительно, что они внутренне не могут много выиграть.
2. Большое вам спасибо. Я должен больше узнать о программировании.