GDAL RasterIO 速度测试程序
简述#
这是很早期的时候写的一个小工具,用来给非开发人员对不同的存储环境进行 GDALRasterIO 的速度进行测试。
最近翻出了这个程序,升级到了 QT 5.15 版本,开源出来供有同样需要的朋友参考吧。
这个工具的原理很简单,就是分别按照 256x256
、512x512
、1024x1024
读取影像的像素数据,读取的时候不会刚刚好从 0,0
坐标开始读,会有一个随机偏移值,以便不会恰好按照影像的分块大小进行读取。
关键代码#
关键代码部分如下:
const int updateblock = 50; void GDALRasterIOSpeedWorker::doGDALRasterIOSpeedTest(QString path) { QString msg; int allblockcount = 0; GDALDatasetH hDset = GDALOpen(toU8String(path).c_str(), GA_ReadOnly); if (hDset == NULL) { msg = QString::fromUtf8(CPLGetLastErrorMsg()); emit doGDALRasterIOSpeedTestMsg(msg); emit doGDALRasterIOSpeedTestFinished(); return; } std::unique_ptr<void, void (*)(GDALDatasetH)> dsetptr(hDset, GDALClose); msg = path + QStringLiteral(" 影像打开成功"); emit doGDALRasterIOSpeedTestMsg(msg); int nBands = GDALGetRasterCount(hDset); msg = QStringLiteral("影像波段数为: ") + QString::number(nBands); emit doGDALRasterIOSpeedTestMsg(msg); if (nBands < 1) { msg = QStringLiteral("没有可用影像波段"); emit doGDALRasterIOSpeedTestMsg(msg); emit doGDALRasterIOSpeedTestFinished(); return; } if (nBands > 16) { nBands = 16; } GDALRasterBandH hBand = GDALGetRasterBand(hDset, 1); int width = GDALGetRasterBandXSize(hBand); int hight = GDALGetRasterBandYSize(hBand); int nXSzie, nYSize; GDALGetBlockSize(hBand, &nXSzie, &nYSize); GDALDataType datatype = GDALGetRasterDataType(hBand); msg = QStringLiteral("影像大小: ") + QString::number(width) + QString('X') + QString::number(hight) + QStringLiteral(" 存储分块大小: ") + QString::number(nXSzie) + QString('X') + QString::number(nYSize) + QStringLiteral(" 数据类型: ") + GDALGetDataTypeName(datatype); emit doGDALRasterIOSpeedTestMsg(msg); if (width < 4096 || hight < 4096) { msg = QStringLiteral("图像太小,不支持小图测试"); emit doGDALRasterIOSpeedTestMsg(msg); emit doGDALRasterIOSpeedTestFinished(); return; } if (width > 20480) { width = 20480; } if (hight > 20480) { hight = 20480; } msg = QStringLiteral("开始测速"); emit doGDALRasterIOSpeedTestMsg(msg); std::vector<uint64_t> buffer((size_t)(1024 * 1024 * nBands), 0); std::function<void(QString, int, int&, int&, int)> func = [nBands, width, hight, datatype, buffer, this]( QString Path, int blocksize, int& blockcount, int& allblockcount, int mode) { std::vector<std::pair<int, int>> xy0; // mode 0:行优先读取; 1:列优先; 2随机 if (mode == 0) { // 读取起点的初始值设置在 16~31 之间的随机数 for (int y = 16 + (rand() % 16); y < hight; y += blocksize) { for (int x = 16 + (rand() % 16); x < width; x += blocksize) { xy0.push_back(std::make_pair(x, y)); } } } else { for (int x = 16 + (rand() % 16); x < width; x += blocksize) { for (int y = 16 + (rand() % 16); y < hight; y += blocksize) { xy0.push_back(std::make_pair(x, y)); } } } if (mode == 2) { std::random_shuffle(xy0.begin(), xy0.end()); } for (const auto& xy : xy0) { int x = xy.first; int y = xy.second; int rw = (width - x) > blocksize ? blocksize : (width - x); int rh = (hight - y) > blocksize ? blocksize : (hight - y); GDALDatasetH hDset = GDALOpen(toU8String(Path).c_str(), GA_ReadOnly); if (hDset == NULL) { continue; } CPLErr err = GDALDatasetRasterIO(hDset, GF_Read, x, y, rw, rh, (void*)buffer.data(), rw, rh, datatype, nBands, NULL, 0, 0, 0); if (err == CPLE_None) { ++blockcount; } ++allblockcount; if (allblockcount % updateblock == 1) { emit this->doGDALRasterIOSpeedTestBlockNumber(allblockcount); } GDALClose(hDset); } }; auto runTestFunc = [this, path, func]( QString title, int mode, int blocksize, int& allblockcount) { int blockcount = 0; QElapsedTimer et; et.start(); func(path, blocksize, blockcount, allblockcount, mode); qint64 elapsed = et.elapsed(); QString msg = title + QStringLiteral(" 读取总块数:") + QString::number(blockcount) + QStringLiteral(" 读取总耗时:") + QString::number(elapsed) + QStringLiteral("毫秒\n") + QStringLiteral("平均每块耗时:") + QString::number(double(elapsed) / blockcount) + QStringLiteral("毫秒\n"); emit doGDALRasterIOSpeedTestMsg(msg); }; runTestFunc(QStringLiteral("256分块(行优先)"), 0, 256, allblockcount); runTestFunc(QStringLiteral("256分块(列优先)"), 1, 256, allblockcount); runTestFunc(QStringLiteral("256分块(随机序)"), 2, 256, allblockcount); runTestFunc(QStringLiteral("512分块(行优先)"), 0, 512, allblockcount); runTestFunc(QStringLiteral("512分块(列优先)"), 1, 512, allblockcount); runTestFunc(QStringLiteral("512分块(随机序)"), 2, 512, allblockcount); runTestFunc(QStringLiteral("1024分块(行优先)"), 0, 1024, allblockcount); runTestFunc(QStringLiteral("1024分块(列优先)"), 1, 1024, allblockcount); runTestFunc(QStringLiteral("1024分块(随机序)"), 2, 1024, allblockcount); emit doGDALRasterIOSpeedTestFinished(); return; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2017-05-17 mingw 构建 mysql-connector-c-6.1.9记录