maxfashko 5 Жалоба Опубликовано September 11, 2016 Добрый вечер. Провел тесты следующего кода, в котором реализован ресайз фото на процессоре и видеокарте. Оборудование следующее: Intel® Core™ i5-4670 CPU @ 3.40GHz × 4 GeForce GTX 650/PCIe/SSE2 2Gb GDDR5 Ubuntu 12.04 x64 Результаты грустные: gpu 0.4890(sec) / 2.0448(fps) cpu 0.1623(sec) / 6.1632(fps) Неужели gtx 650 очень дрова? Та же ситуация обстоит с pycuda. Тестовый скрипт ( https://wiki.tiker.net/PyCuda/Examples/SimpleSpeedTest ) выводит следующее время: Using nbr_values == 8192 Calculating 100000 iterations SourceModule time and first three results: 0.080705s, [ 0.005477 0.005477 0.005477] Elementwise time and first three results: 0.161862s, [ 0.005477 0.005477 0.005477] Elementwise Python looping time and first three results: 0.780193s, [ 0.005477 0.005477 0.005477] GPUArray time and first three results: 3.765418s, [ 0.005477 0.005477 0.005477] CPU time and first three results: 2.716871s, [ 0.005477 0.005477 0.005477] #код ресайза фотографий #include <iostream> #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/calib3d.hpp" #include "opencv2/cudalegacy.hpp" #include "opencv2/cudaimgproc.hpp" #include "opencv2/cudaarithm.hpp" #include "opencv2/cudawarping.hpp" #include "opencv2/cudafeatures2d.hpp" #include "opencv2/cudafilters.hpp" #include "opencv2/cudaoptflow.hpp" #include "opencv2/cudabgsegm.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/opencv.hpp" using namespace std; using namespace cv; using namespace cv::cuda; void ProccTimePrint( unsigned long Atime , string msg) { unsigned long Btime=0; float sec, fps; Btime = getTickCount(); sec = (Btime - Atime)/getTickFrequency(); fps = 1/sec; printf("%s %.4lf(sec) / %.4lf(fps) \n", msg.c_str(), sec, fps ); } void processUsingOpenCvGpu(string input_file, string output_file); void processUsingOpenCvCpu(std::string input_file, std::string output_file); int main(){ processUsingOpenCvGpu("/home/maksim/Изображения/1.jpg", "/home/maksim/Изображения/1_rG.jpg"); processUsingOpenCvCpu("/home/maksim/Изображения/1.jpg", "/home/maksim/Изображения/1_rC.jpg"); return 0; } void processUsingOpenCvGpu(string input_file, string output_file) { unsigned long AAtime=0; AAtime = getTickCount(); //Read input image from the disk cv::Mat inputCpu = cv::imread(input_file,CV_LOAD_IMAGE_COLOR); cv::cuda::GpuMat input (inputCpu); if(input.empty()) { cout<<"Image Not Found: "<< input_file << endl; return; } //Create output image cv::cuda::GpuMat output; cv::cuda::resize(input, output, cv::Size(), .05, 0.05, CV_INTER_AREA); // downscale 4x on both x and y ProccTimePrint(AAtime , "gpu"); cv::Mat outputCpu; output.download(outputCpu); cv::imwrite(output_file, outputCpu); input.release(); output.release(); } void processUsingOpenCvCpu(std::string input_file, std::string output_file) { unsigned long AAtime=0; AAtime = getTickCount(); //Read input image from the disk Mat input = imread(input_file, CV_LOAD_IMAGE_COLOR); if(input.empty()) { std::cout<<"Image Not Found: "<< input_file << std::endl; return; } //Create output image Mat output; cv::resize(input, output, Size(), .05, 0.05, CV_INTER_AREA); // downscale 4x on both x and y ProccTimePrint(AAtime , "cpu"); imwrite(output_file, output); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ter_nk 0 Жалоба Опубликовано September 11, 2016 У вас функция resize использует везде один поток. По определению ядро интела мощнее ядра gpu. Графические процессоры отличаются тем, что они очень многоядерные и производительность у них выше за счет совместного использования нескольких ядер. GPU имеет смысл когда вы делаете много однотипных операций на много ядер. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано September 11, 2016 gpu-шные версии opencv-шных команд по-любому используют не одно ядро. Наибольшие издержки обычно возникают при передаче данных host-device и обратно, также занимает время выделение/освобождение памяти (gpuMat), которое у вас в цикле. Еще неплохо бы инициализировать GPU, насколько помню метод setDevice или что то в этом роде, иначе первая операция занимает много времени. Плюс к тому, можно одновременно производить загрузку следующей порции данных и обработку текущей. В общем почитайте, про оптимизацию для CUDA. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано September 12, 2016 В дополнение: сначала посмотрите в кудовский профайлер и посмотрите на источник тормозов. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
maxfashko 5 Жалоба Опубликовано September 12, 2016 Smorodov, вы как всегда правы. Установка девайса помогла снизить время, но по-прежнему, процессор чуть быстрее. Gpu 0.1892 Cpu 0.1600 Дело в том, что программа построена так, что процесс ресайза это не главное действие, после ресайза изображение поступает на дальнейшую обработку, там пакетной обработки даже нет. Только если создавать несколько потоков, и одновременно обрабатывать несколько изображений. Сначала класссификация, затем ресайз, после этого сегментация. И так каждое изображение в своем потоке? Nuzhny, где это можно сделать? Подробнее пожалуйста. Компилятор не может наложить какие либо особенности? Компилировал nvcc resize.cpp -o resize 'pkg-config --cflags --libs opencv' -lopencv_gpu Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано September 12, 2016 Просто запусти профайлер, который вместе с CUDA идёт и уже из него свой код. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
maxfashko 5 Жалоба Опубликовано September 12, 2016 В общем gui profiler никак не хотел загружать скомпилированное приложение, выдавал ошибку поэтому воспользовался версией для командной строки, но информации очень мало выдал. ==5705== Profiling result: Time(%) Time Calls Avg Min Max Name 73.18% 24.757ms 1 24.757ms 24.757ms 24.757ms void cv::cuda::device::resize_area<cv::cuda::device::IntegerAreaFilter<cv::cuda::device::BorderReader<cv::cuda::PtrStep<uchar3>, cv::cuda::device::BrdConstant<uchar3>>>, uchar3>(uchar3, cv::cuda::PtrStepSz<cv::cuda::PtrStep<uchar3>>) 26.79% 9.0619ms 1 9.0619ms 9.0619ms 9.0619ms [CUDA memcpy HtoD] 0.04% 12.992us 1 12.992us 12.992us 12.992us [CUDA memcpy DtoH] Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано September 19, 2016 Не написано какого размера изображение, неплохо было бы вывести график зависимости времени от размера изображения. Тут не используется многопоточность на CPU, только если внутри самого resize, тоже и для GPU по идее можно кидать данные батчами. Еще когда будете использовать многопоточный код важно померить именно wallclock time. boost::timer::cpu_timer timer; ... boost::timer::cpu_times elapsed = timer.elapsed(); cout << "Processing : "<< " WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl; Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах