CPU: AMD Ryzen 5 5600X 6-Core Processor 3.70 GHz
内存:32.0 GB
C++ vs2017 MSVC编译器工具集
python 3.6.8
测试图片有两类:数据集1 血片细胞图片尺寸:2448*2048.
数据集2 网上随机下载的自然风光,人物,汽车等20张图片,尺寸在471 *600 至 2048 *1536之间。
注:图片的大小对测试结果应该有比较大的影响。
1. Python
start_time = time.clock()
img = cv2.imread(file_name)
end_time = time.clock()
total = total + (end_time-start_time)
2. C++
const auto start_t = std::chrono::high_resolution_clock::now();
for (size_t i = 0; i < 15; i++)
{
//std::cout << files[i].c_str() << std::endl;
//opencv decode
cv::Mat image = cv::imread(files[i].c_str());
}
const auto end_t = std::chrono::high_resolution_clock::now();
std::cout << "read image cost:" << std::chrono::duration(end_t - start_t).count() << "ms" << std::endl;
3. 耗时
语言 | 单张平均耗时(ms) | 15张总耗时(ms) |
---|---|---|
Python | 37.90 | 568.49 |
C++ | 30.92 | 463.82 |
注:c++采用release模式,不能用debug。且每次执行时间不一样,多执行几次取了一个中间值。
语言 | 单张平均耗时(ms) | 20张总耗时(ms) |
---|---|---|
Python | 7.18 | 143.69 |
C++ | 5.38 | 107.69 |
注:cc++采用release模式,不能用debug。且每次执行时间不一样,多执行几次取了一个中间值。
环境与1一致
resize 的大小都是到(224,224)
核心代码
1. Python
start_time = time.clock()
img = cv2.resize(img,(224,224))
end_time = time.clock()
total = total + (end_time-start_time)
print('costs time : ',total)
2. C++
std::chrono::duration total;
for (size_t i = 0; i < 20; i++)
{
//std::cout << files[i].c_str() << std::endl;
//opencv decode
cv::Mat image = cv::imread(files[i].c_str());
const auto start_t = std::chrono::high_resolution_clock::now();
cv::resize(image, resized_image, cv::Size(224, 224));
const auto end_t = std::chrono::high_resolution_clock::now();
total = total + (end_t - start_t);
//std::cout << "read image cost:" << std::chrono::duration(end_t - start_t).count() << "ms" << std::endl;
}
std::cout << "read image cost:" << total.count() << "ms" << std::endl;
3. 耗时
语言 | 单张平均耗时(ms) | 15张总耗时(ms) |
---|---|---|
Python | 0.57 | 8.54 |
C++ | 0.34 | 5.10 |
注:c++采用release模式,不能用debug。且每次执行时间不一样,多执行几次取了一个中间值。
语言 | 单张平均耗时(ms) | 20张总耗时(ms) |
---|---|---|
Python | 0.24 | 4.98 |
C++ | 0.14 | 2.87 |
注:c++采用release模式,不能用debug。且每次执行时间不一样,多执行几次取了一个中间值。
CPU: AMD Ryzen 5 5600X 6-Core Processor 3.70 GHz
内存:32.0 GB
C++ vs2017 MSVC编译器工具集
NVJPEG 是cuda11.1版本
数据集3:血片图片resize 到不同尺寸保存的图片。[32,64,128,224,360,480,640,720,960,1080,1280,1920,2048,3120]
2.代码
NVJPEG Sample 测试代码来自于nvJPEG项目
NVJPEG guide
3. C++ opencv 在数据集3测试平均解码时间(ms)
解码方式 | 32 | 64 | 128 | 224 | 480 | 720 | 960 | 1080 | 1280 | 2048 | 3120 |
---|---|---|---|---|---|---|---|---|---|---|---|
Opencv(C++) | 0.112 | 0.152 | 0.330 | 0.677 | 2.651 | 6.021 | 10.410 | 12.710 | 17.295 | 38.871 | 79.160 |
NVJPEG | 0.360 | 0.350 | 0.380 | 0.370 | 0.489 | 0.640 | 0.810 | 1.04 | 1.28 | 2.230 | 2.420 |
注:nvjpeg 在224及之前的尺寸时间几乎没有差异。
对于resize 操作使用的是NPP库,基于cuda写的图像处理的库。当我们在做深度学习推理时,需要对图像预处理时,希望推理时预处理与训练是预处理保持一致,那么很显然推理使用cuda加速预处理后希望把数据的排列(如:nchw)保持一致。而如果基于nvjpeg使用cuda处理,数据是按照gpu需要的排列进行计算,因此无论解码和预处理如何在cuda计算,处理完的数据排列必然要清楚,要么就老老实实的转化为cv:mat的方式。
回到测试resize的话题,由于要使用cuda做resize,则需要对输入数据进行排列,最方便的形式就是只用nvjpeg解码,直接加载到cuda内存中,resize也可按照的解码的格式进行resize,因此,resize应该和decode配套使用效率才是最高的。另外,resize结束应该按照什么数据排列作为resize结束呢?按照两种方式,第一是nvjpeg的数据格式作为结束,记为NVJPEG_OUTPUT_BGR
,第二是重新排列到cv::Mat格式作为结束,记为cv::Mat
。
以下测试的内容包括jpeg decode和resize的时间。resize 的大小都是到(224,224)
单张平均耗时(ms) | 15张总耗时(ms) | |
---|---|---|
Python | 44.47 | 667 |
C++ | 38.11 | 571.65 |
NVJPEG | 3.64 | 54.69 |
单张平均耗时(ms) | 20张总耗时(ms) | |
---|---|---|
Python | 7.65 | 153.17 |
C++ | 5.72 | 114.4 |
NVJPEG | 2.63 | 52.71 |
注:nvjpeg计算的时间都是计算cuda计算时间,没有考虑初始化准备的时间
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
char *filePath = (char*)"D:\\image_decode\\data";
std::vector files;
getFiles(filePath, files);
int img_num = 15;
cv::Mat resized_image(224, 224, CV_8UC3);
const auto start_t = std::chrono::high_resolution_clock::now();
//std::chrono::duration total;
for (size_t i = 0; i < img_num; i++)
{
//std::cout << files[i].c_str() << std::endl;
//opencv decode
cv::Mat image = cv::imread(files[i].c_str());
//const auto start_t = std::chrono::high_resolution_clock::now();
cv::resize(image, resized_image, cv::Size(224, 224));
cv::imwrite("result.jpg", resized_image);
//const auto end_t = std::chrono::high_resolution_clock::now();
//total = total + (end_t - start_t);
}
const auto end_t = std::chrono::high_resolution_clock::now();
std::cout << "read image cost:" << std::chrono::duration(end_t - start_t).count()/ img_num << "ms" << std::endl;
//std::cout << "read image cost:" << total.count() << "ms" << std::endl;
}
单张平均耗时(ms) | 15张总耗时(ms) | |
---|---|---|
Python | 45.92 | 688.82 |
C++ | 39.28 | 589.2 |
NVJPEG | 3.97 | 59.63 |
单张平均耗时(ms) | 20张总耗时(ms) | |
---|---|---|
Python | 8.56 | 171.16 |
C++ | 6.80 | 136 |
NVJPEG | 2.91 | 58.18 |
注:nvjpeg计算的时间都是计算cuda计算时间,没有考虑初始化的时间
思考的问题
数据预处理阶段,resize结束后,还有归一化,nchw排列的计算,这部分还可以可以加速?