在C++11推出自己的标准线程库std::thread之后,也使得将std::thread与遥感影像的分块读写相结合成为可能,而且使用std::thread进行影像分块读写多线程处理更为方便安全(以前使用较多的还是openmp,或者是原生的pthread库)
先看一段代码截图:
该函数是单个线程执行函数,形参为一个结构体,传递每一块的基本参数,nXOffset, nYOffset, nBlockXSize, nBlockYSize
(注意:在该函数内部,申请的内存空间是各线程各自独有的,往该内存写入操作不用加互斥锁)
关注点1:读数据时
各线程按照各自的块参数读数据时,是可以同时读取的,不用加锁操作。
如上图所示,先申请读数据所需内存空间,然后获取数据集指针,再读入每块对应的数据到内存。
但需要注意的是,红框部分是重点:
如果整个程序不使用多线程处理:此处读数据所需的 GDALDataset* 指针实例完全可以使用前面已经打开影像并指向数据集的指针变量;
如果使用多线程处理:则必须在线程处理函数中,重新打开输入影像获取指向输入影像数据集的指针变量,然后以此来读取数据(也就是说,每个线程都必须独立拥有指向数据集的指针,否则多线程读取会发生错误)
关注点2:写数据时
多线程写数据时,肯定不能同时写,必须使用互斥锁实现线程同步
如上图所示, 使用std::mutex类型的m_WriteMtx互斥锁构造一个uniq_lock,在该作用域内,构造时(进该作用域时)加锁,析构时(出该作用域时)释放锁,非常经典的RAII思想,保障了多线程执行下面写数据代码时的同步性。
使用 std::lock_guard<std::mutex> grd_lock(m_WriteMtx); 也可以
(注意:写数据时,每个线程也必须独立拥有指向输出数据集的指针,且以更新的方式打开)
(还有一点需要注意:在执行多线程写数据时,也就是在执行该线程处理函数之前,如果已经有了指向输出数据集的指针时,需要先将其GDALClose(xxxptr)关闭,然后在执行这里的多线程写,否则写数据也会出问题;如果单线程跑代码,则不需要提前关闭数据集指针)
以上就是一些关于多线程影像分块读写的经验分享。