如何优化OpenCV中cv::Mat的初始化耗时?
问题描述
程序启动时需要初始化16个指定尺寸、默认黑色像素的cv::Mat变量,通过如下函数逐个完成初始化操作。在Intel W-2295 3.00 GHz处理器、Windows系统Visual Studio 2022 Release模式下,该初始化过程耗时约22秒。请问此过程耗时较长的原因是什么?又该如何优化耗时?
int init_mat(cv::Mat& mat) { cv::Size size_from_config(80000, 3000); mat = cv::Mat(size_from_config, CV_8UC3, cv::Vec3b(0, 0, 0)); return EXIT_SUCCESS; }
耗时原因分析
- 内存占用过大且逐像素初始化:单个
cv::Mat的尺寸是80000×3000,每个像素占3字节,计算下来单张图内存为8000030003 = 720,000,000字节(约686MB),16张总内存超过11GB。创建cv::Mat时,OpenCV会逐像素写入cv::Vec3b(0,0,0),这种逐像素赋值的操作在内存量极大时会产生大量CPU开销,同时大内存分配也会触发系统内存管理的额外工作(比如虚拟内存页调度)。 - 默认内存分配机制的开销:OpenCV默认的内存分配器在处理超大内存块时,可能会因为内存碎片、连续内存块申请困难等问题,导致分配和初始化的耗时增加。
- 单线程串行初始化:当前是逐个调用函数初始化,所有操作都在单线程执行,完全没有利用多核CPU的并行能力,Intel W-2295是18核36线程的处理器,单线程处理11GB级别的内存写入完全浪费了硬件资源。
优化方案
跳过逐像素初始化,利用内存零填充机制
可以直接申请内存而不手动赋值黑色,因为系统分配的内存如果是从虚拟内存页映射来的,Windows会自动将新页初始化为零(对应黑色像素)。修改方式:int init_mat(cv::Mat& mat) { cv::Size size_from_config(80000, 3000); // 创建不初始化数据的Mat,之后系统会自动将内存置零 mat = cv::Mat(size_from_config, CV_8UC3); return EXIT_SUCCESS; }或者使用
cv::Mat::create方法,同样可以避免显式初始化:mat.create(size_from_config, CV_8UC3);这种方式能省去逐像素写入的CPU开销,直接利用系统零页机制,大幅缩短初始化时间。
并行化初始化
利用OpenMP或C++标准库的线程池,将16个cv::Mat的初始化任务分配到多个线程并行执行。比如用OpenMP:// 假设是在循环中调用init_mat #pragma omp parallel for num_threads(16) for(int i=0; i<16; i++){ init_mat(mats[i]); }这样可以充分利用Intel W-2295的多核优势,把串行的耗时分散到多个线程,整体时间会大幅下降。
使用高效内存分配器
可以切换OpenCV的内存分配器为更适合大内存块的类型,或者在Windows下启用大页内存分配,减少内存页调度的开销。比如配置系统大页权限后,让OpenCV使用大页内存,能降低大内存块分配时的碎片化问题,提升分配效率。
内容的提问来源于stack exchange,提问作者gear
相关产品推荐
相关产品推荐

