Перейти к содержимому
Compvision.ru
maxfashko

cpu быстрее gpu

Recommended Posts

Добрый вечер. Провел тесты следующего кода, в котором реализован ресайз фото на процессоре и видеокарте. Оборудование следующее:

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);
}


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

У вас функция resize использует везде один поток. По определению ядро интела мощнее ядра gpu. Графические процессоры отличаются тем, что они очень многоядерные и производительность у них выше за счет совместного использования нескольких ядер. GPU имеет смысл когда вы делаете много однотипных операций на много ядер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

gpu-шные версии opencv-шных команд по-любому используют не одно ядро.

Наибольшие издержки обычно возникают при передаче данных host-device и обратно, также занимает время выделение/освобождение памяти (gpuMat), которое у вас в цикле.

Еще неплохо бы инициализировать GPU, насколько помню метод setDevice или что то в этом роде, иначе первая операция занимает много времени.

Плюс к тому, можно одновременно производить загрузку следующей порции данных и обработку текущей.

В общем почитайте, про оптимизацию для CUDA. 

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В дополнение: сначала посмотрите в кудовский профайлер и посмотрите на источник тормозов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Smorodov, вы как всегда правы. Установка девайса помогла снизить время, но по-прежнему, процессор чуть быстрее.

Gpu 0.1892

Cpu 0.1600

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

Nuzhny, где это можно сделать? Подробнее пожалуйста.

 

Компилятор не может наложить какие либо особенности?

Компилировал nvcc resize.cpp -o resize 'pkg-config --cflags --libs opencv' -lopencv_gpu

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Просто запусти профайлер, который вместе с CUDA идёт и уже из него свой код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В общем 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]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не написано какого размера изображение, неплохо было бы вывести график зависимости времени от размера изображения.

Тут не используется многопоточность на 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;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×