このページでは

並行MapおよびMap-Reduce

QtConcurrent::map()、QtConcurrent::mapped()、および QtConcurrent::mappedReduced() 関数は、QList などのシーケンス内の項目に対して計算を並列に実行します。 QtConcurrent::map() はシーケンスをその場で変更し、QtConcurrent::mapped() は変更後の内容を含む新しいシーケンスを返し、QtConcurrent::mappedReduced() は単一の結果を返します。

これらの関数は Qt Concurrent フレームワークの一部です。

上記の各関数には、QFuture の代わりに最終結果を返すブロッキング型のバリエーションがあります。これらは、非同期型のバリエーションと同じ方法で使用します。

QList<QImage> images = ...;

// Each call blocks until the entire operation is finished.
QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);

QtConcurrent::blockingMap(images, scale);

QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);

なお、上記の結果型はQFuture オブジェクトではなく、実際の結果型(この場合はQList<QImage>およびQImage)であることに注意してください。

インクルードファイルの最適化

<QtConcurrent> ヘッダをインクルードすると、Qt Concurrent モジュール全体とQt Core モジュール全体がインクルードされるため、コンパイル時間やバイナリサイズが増加する可能性があります。QtConcurrent::map()、QtConcurrent::mapped()、およびQtConcurrent::mappedReduced() 関数を使用するには、より具体的なヘッダをインクルードすることができます:

#include <QtConcurrentMap>

並行マップ

QtConcurrent::mapped() は、入力シーケンスとマップ関数を受け取ります。このマップ関数は、シーケンス内の各項目に対して呼び出され、マップ関数の戻り値を含む新しいシーケンスが返されます。

map関数は、以下の形式で定義する必要があります:

U function(const T &t);

T と U は任意の型(同じ型であってもよい)ですが、T はシーケンスに格納されている型と一致する必要があります。この関数は、変更またはマップ処理された内容を返します。

この例は、シーケンス内のすべての要素にスケーリング関数を適用する方法を示しています:

QImage scaled(const QImage &image)
{
    return image.scaled(100, 100);
}

QList<QImage> images = ...;
QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);

mapの結果は、QFuture を通じて利用可能です。アプリケーションでのQFuture の使用方法に関する詳細については、QFuture およびQFutureWatcher のドキュメントを参照してください。

シーケンスをその場で変更したい場合は、QtConcurrent::map() を使用します。その場合、map 関数は以下の形式で記述する必要があります:

U function(T &t);

なお、map関数の戻り値および戻り値の型は使用されません。

QtConcurrent::map() の使用方法は、QtConcurrent::mapped() の使用方法と似ています:

void scale(QImage &image)
{
    image = image.scaled(100, 100);
}

QList<QImage> images = ...;
QFuture<void> future = QtConcurrent::map(images, scale);

シーケンスはインプレースで変更されるため、QtConcurrent::map()はQFuture を介して結果を返しません。ただし、QFuture やQFutureWatcher を使用して、mapのステータスを監視することは可能です。

並行マッピングと継続

QtConcurrent::mapped() の呼び出し結果は、複数の結果を含むQFuture です。このようなQFuture に.then() 継続をアタッチする際は、必ずQFuture をパラメータとして受け取る継続を使用してください。そうしないと、最初の結果のみが処理されてしまいます:

autoprocess= [](intval) {
    returnval* 2;
};

QList<int>inputs {1, 2, 3};
autobadFuture=QtConcurrent::mapped(inputs,process)
                         .then([](intval) {
                             qDebug() << val;
                         });

autogoodFuture=QtConcurrent::mapped(inputs,process)
                          .then([](QFuture<int>f) {
                              for(autor : f.results()) {
                                  qDebug() << r;
                              }
                          });

この例では、badFuture は 1 つの結果のみを出力しますが、goodFuture はすべての結果を出力します。

並行 Map-Reduce

QtConcurrent::mappedReduced() は QtConcurrent::mapped() と似ていますが、新しい結果を含むシーケンスを返す代わりに、リデュース関数を使用して結果を単一の値に結合します。

reduce関数は、以下の形式で定義する必要があります:

V function(T &result, const U &intermediate)

ここで、T は最終結果の型、U は map 関数の戻り値の型です。なお、reduce 関数の戻り値および戻り値の型は使用されないことに注意してください。

QtConcurrent::mappedReduced() は次のように呼び出します:

void addToCollage(QImage &collage, const QImage &thumbnail)
{
    QPainter p(&collage);
    static QPoint offset = QPoint(0, 0);
    p.drawImage(offset, thumbnail);
    offset += ...;
}

QList<QImage> images = ...;
QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);

reduce関数は、map関数が返す結果ごとに1回ずつ呼び出され、中間結果をresult変数に統合する必要があります。QtConcurrent::mappedReduced()は、一度に1つのスレッドのみがreduceを呼び出すことを保証しているため、mutexを使用してresult変数をロックする必要はありません。QtConcurrent::ReduceOptions 列挙型を使用することで、リダクションが実行される順序を制御できます。QtConcurrent::UnorderedReduce (デフォルト)を使用した場合、順序は未定義となりますが、QtConcurrent::OrderedReduce を指定すると、リダクションが元のシーケンスの順序で実行されることが保証されます。

その他のAPI機能

Sequenceの代わりにイテレータを使用する

上記の各関数には、シーケンスの代わりにイテレータ範囲を受け取るバリエーションがあります。これらは、シーケンスを受け取るバリエーションと同じように使用します:

QList<QImage> images = ...;

QFuture<QImage> thumbnails = QtConcurrent::mapped(images.constBegin(), images.constEnd(), scaled);

// Map in-place only works on non-const iterators.
QFuture<void> future = QtConcurrent::map(images.begin(), images.end(), scale);

QFuture<QImage> collage = QtConcurrent::mappedReduced(images.constBegin(), images.constEnd(), scaled, addToCollage);

ブロッキング型

上記の各関数には、QFuture の代わりに最終結果を返すブロッキング型があります。これらは非同期型と同じように使用します。

QList<QImage> images = ...;

// Each call blocks until the entire operation is finished.
QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);

QtConcurrent::blockingMap(images, scale);

QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);

なお、上記の結果型はQFuture オブジェクトではなく、実際の結果型(この場合はQList<QImage>およびQImage)であることに注意してください。

メンバ関数の使用

QtConcurrent::map()、QtConcurrent::mapped()、および QtConcurrent::mappedReduced() は、メンバ関数へのポインタを受け取ります。メンバ関数のクラス型は、シーケンスに格納されている型と一致している必要があります。

// QStringList内のすべての文字列を圧縮する。
QStringList strings=...;
QFuture<void>squeezedStrings=QtConcurrent::map(strings, &QString::squeeze);

// 画像のリストに含まれるすべてのピクセルのRGB値を反転させる。
QList<QImage>images=...;
QFuture<QImage>bgrImages=QtConcurrent::mapped(images,
    static_cast<QImage(QImage::*)()const &>(&QImage::rgbSwapped));

// リスト内のすべての文字列の長さの集合を作成する。
QStringList strings=...;
QFuture<QSet<int>>wordLengths=QtConcurrent::mappedReduced(strings, &QString::length,
                                                             qOverload<const int&>(&QSet<int>::insert));

qOverload の使用に注意してください。これは、複数のオーバーロードを持つメソッドの曖昧さを解消するために必要です。

また、QtConcurrent::mappedReduced() を使用する場合、通常の関数とメンバ関数を自由に組み合わせて使用できる点にも注意してください:

// QtConcurrent::mappedReduced() では、通常の関数とメンバ関数を混在させることができます。

// 文字列のリストの平均長を計算します。
extern voidcomputeAverage(int &average, intlength);
QStringList strings=...;
QFuture<int>averageWordLength=QtConcurrent::mappedReduced(strings, &QString::length,computeAverage);

// リスト内のすべての画像の色分布を表すセットを作成する。
extern intcolorDistribution(const QImage &string);
QList<QImage>images=...;
QFuture<QSet<int>>totalColorDistribution=QtConcurrent::mappedReduced(images,colorDistribution,
                                                                        qOverload<const int&>(&QSet<int>::insert));

関数オブジェクトの使用

QtConcurrent::map()、QtConcurrent::mapped()、および QtConcurrent::mappedReduced() は、map 関数として関数オブジェクトを受け付けます。これらの関数オブジェクトを使用すると、関数呼び出しに状態を追加することができます:

struct Scaled
{
    Scaled(int size)
    : m_size(size) { }

    typedef QImage result_type;

    QImage operator()(const QImage &image)
    {
        return image.scaled(m_size, m_size);
    }

    int m_size;
};

QList<QImage> images = ...;
QFuture<QImage> thumbnails = QtConcurrent::mapped(images, Scaled(100));

reduce関数に対しても、関数オブジェクトがサポートされています:

struct ImageTransform
{
    void operator()(QImage &result, const QImage &value);
};

QFuture<QImage> thumbNails =
        QtConcurrent::mappedReduced(images, Scaled(100), ImageTransform(),
                                    QtConcurrent::SequentialReduce);

ラムダ式の使用

QtConcurrent::map()、QtConcurrent::mapped()、および QtConcurrent::mappedReduced() は、map 関数および reduce 関数としてラムダ式を受け付けます:

QList<int> vector { 1, 2, 3, 4 };
QtConcurrent::blockingMap(vector, [](int &x) { x *= 2; });

int size = 100;
QList<QImage> images = ...;

QList<QImage> thumbnails = QtConcurrent::mapped(images,
        [&size](const QImage &image) {
            return image.scaled(size, size);
        }
    ).results();

QtConcurrent::mappedReduced() または QtConcurrent::blockingMappedReduced() を使用する場合、通常の関数、メンバ関数、およびラムダ式を自由に組み合わせて使用できます。

QList<QImage> collage = QtConcurrent::mappedReduced(images,
        [&size](const QImage &image) {
            return image.scaled(size, size);
        },
        addToCollage
   ).results();

また、ラムダ式をreduceオブジェクトとして渡すこともできます:

QList<QImage> collage = QtConcurrent::mappedReduced(images,
        [&size](const QImage &image) {
            return image.scaled(size, size);
        },
        [](QImage &result, const QImage &value) {
            // do some transformation
        }
   ).results();

複数の引数を取る関数のラッピング

複数の引数を取るマップ関数を使用したい場合は、ラムダ関数またはstd::bind() を使用して、それを1つの引数を取る関数に変換することができます。

例として、QImage::scaledToWidth() を使用します:

QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const;

scaledToWidth は 3 つの引数(「this」ポインタを含む)を受け取りますが、QtConcurrent::mapped() は 1 つの引数を受け取る関数を期待するため、scaledToWidth を直接 QtConcurrent::mapped() で使用することはできません。 QImage::scaledToWidth()をQtConcurrent::mapped()で使用するには、幅と変換モードの値を指定する必要があります:

QList<QImage> images = ...;
std::function<QImage(const QImage &)> scale = [](const QImage &img) {
    return img.scaledToWidth(100, Qt::SmoothTransformation);
};
QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scale);

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.