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