Производительность OpenCV GAPI не так хороша, как ожидалось - PullRequest
0 голосов
/ 11 марта 2020

Я делаю следующий тест, однако результат не так хорош, потому что я sh, что GAPI мог бы значительно улучшить. Я не знаю, сделал ли я что-то не так, надеюсь, вы поможете мне исправить, спасибо большое!

Моя тестовая среда - официальная сборка OpenCV4.2, Windows 10 x64, выпуск VS2019 x64, i7-8700K.

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/imgproc.hpp>

std::string image_path = "1.png";
cv::Mat GAPITEST(const cv::Mat& input_frame)
{
    cv::Mat output_frame;

    cv::GMat in;
    cv::GMat vga = cv::gapi::resize(in, cv::Size(), 0.5, 0.5);
    cv::GMat gray = cv::gapi::BGR2Gray(vga);
    cv::GMat blurred = cv::gapi::blur(gray, cv::Size(5, 5));
    cv::GMat out = cv::gapi::Canny(blurred, 32, 128, 3);
    cv::GComputation ac(in, out);

    int64 t0 = cv::getTickCount();
    for(int i=0;i<200;i++)
        ac.apply(input_frame, output_frame);
    int64 t1 = cv::getTickCount();
    std::cout <<__func__<< "\t seconds:" << (t1 - t0) / cv::getTickFrequency()<<std::endl;

    return output_frame;
}

cv::Mat TraditionalTEST(const cv::Mat& input_frame)
{
    cv::Mat output_frame;
    cv::Mat vga;
    cv::Mat gray;
    cv::Mat blurred;

    int64 t0 = cv::getTickCount();
    for (int i = 0; i < 200; i++)
    {
        cv::resize(input_frame,vga, cv::Size(), 0.5, 0.5);
        cv::cvtColor(vga, gray, cv::COLOR_BGR2GRAY);
        cv::blur(gray, blurred,cv::Size(5,5));
        cv::Canny(blurred,output_frame,32,128,3);
    }
    int64 t1 = cv::getTickCount();
    std::cout << __func__ << "\t seconds:" << (t1 - t0) / cv::getTickFrequency()<<std::endl;
    return output_frame;
}
int main()
{
    cv::Mat input_frame = cv::imread(image_path);
    cv::imshow("input_frame",input_frame);
    cv::waitKey(100);
    auto result1 = GAPITEST(input_frame);
    auto result2 = TraditionalTEST(input_frame);
    //check result whether identical or not.
    bool eq = cv::countNonZero(result1 != result2) == 0;
    std::cout << "result equal  "<< eq;
    return 0;
}

outut

GAPITEST         seconds:4.92153
TraditionalTEST  seconds:4.68761
result equal  1

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

команда G-API находится на связи!

Как уже упоминал Алекс, сравнение выполняемого по умолчанию G-API с аналоговым кодом OpenCV пока не сильно улучшит вашу производительность.

Бэкэнд Fluid делает свое дело, но пока он все еще однопоточный. Это означает, что он не сильно выиграет от обычного кода OpenCV, который по умолчанию является многопоточным.

Возможно, вы захотите попробовать бэкэнд Fluid, но протестируйте с setNumThreads(1), чтобы заметить разницу. Чем больше ваше входное изображение (с точки зрения разрешения), тем больший эффект вы должны видеть там.

Также я рекомендую вам прочитать эти новые учебные пособия:

  1. https://docs.opencv.org/4.3.0/d8/d24/tutorial_gapi_interactive_face_detection.html
  2. https://docs.opencv.org/4.3.0/d4/d48/tutorial_gapi_face_beautification.html

Мы теперь уделяем больше внимания гибридному выполнению CV / DL и обработке, ориентированной на видеопоток.


ADDED

G-API поставляется с простым тестом, иллюстрирующим вышеупомянутый «G-эффект», хотя тесты не являются частью обычного (двоичного) распространение OpenCV или OpenVINO:

https://github.com/opencv/opencv/blob/master/modules/gapi/perf/perf_bench.cpp

Если вы создадите OpenCV самостоятельно (или просто цель opencv_perf_gapi), вы сможете запустить это как

./bin/opencv_perf_gapi --gtest_filter="Benchmark*"

Мне бы очень хотелось увидеть числа, которые вы получите на своей машине.

1 голос
/ 11 марта 2020

GAPI все еще находится на ранней стадии разработки, и его производительность на одной машине довольно дрянная. Сам GAPI изначально не предназначен для непосредственного вычисления алгоритмов, поэтому он использует внутренние библиотеки для выполнения вычислений. По умолчанию используется бэкэнд по умолчанию OpenCV, который отстой. Вы можете заменить его на бэкэнд Fluid, который предположительно имеет лучшую локальность кэша при выполнении алгоритмов, но он все еще отстой в моих нескольких тестах.

В этих бэкэндах очень мало реализаций базовых c функций OpenCV (например, Fluid поддерживает только ядра 3x3 для блочных фильтров), а GComputation :: apply будет неблагоразумно создавать sh при использовании неподдерживаемой операции, часто без каких-либо полезных сообщений об ошибках.

В GAPI замечательно то, что графовая модель это реализует аппаратно-агностичность c. Вы можете взять созданный им график и передать его в облачную или распределенную вычислительную систему с несколькими графическими процессорами, процессорами и т. Д., И она будет в полной мере использовать ресурсы, доступные для него автоматически.

Если вы хотите быстро производительность на одной машине, я рекомендую использовать cv :: cuda :: GpuMat. Я часто использую это, и оно быстро работает во многих операциях. Это избавляет от необходимости писать собственные ядра CUDA.

Я не могу поручиться за UMat или другое качество реализации GPU, потому что я когда-либо использовал OpenCV только с картами Nvidia.

Вы также можете посмотреть в компиляцию OpenCV с поддержкой OpenMP для производительности.

Во всяком случае, это своего рода ответ на дробовик. Go здесь для получения более подробной информации о GAPI и более полной тестовой программе, сравнивающей несколько бэкэндов: https://docs.opencv.org/master/d3/d7a/tutorial_gapi_anisotropic_segmentation.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...