GDAL RasterIO 速度测试程序

简述

这是很早期的时候写的一个小工具,用来给非开发人员对不同的存储环境进行 GDALRasterIO 的速度进行测试。
最近翻出了这个程序,升级到了 QT 5.15 版本,开源出来供有同样需要的朋友参考吧。

这个工具的原理很简单,就是分别按照 256x256512x5121024x1024 读取影像的像素数据,读取的时候不会刚刚好从 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;
}

项目git仓库

仓库地址: https://gitee.com/solym/GDALRasterIOSpeed.git

posted @ 2021-05-17 17:53  乌合之众  阅读(579)  评论(0编辑  收藏  举报
clear