병렬 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);맵의 결과는 ` 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 를 매개변수로 받는 연속체를 사용해야 합니다. 그렇지 않으면 첫 번째 결과만 처리됩니다:
auto process = [](int val) {
return val * 2;
};
QList<int> inputs { 1, 2, 3 };
auto badFuture = QtConcurrent::mapped(inputs, process)
.then([](int val) {
qDebug() << val;
});
auto goodFuture = QtConcurrent::mapped(inputs, process)
.then([](QFuture<int> f) {
for (auto r : f.results()) {
qDebug() << r;
}
});이 예제에서 badFuture 은 하나의 결과만 출력하는 반면, goodFuture 은 모든 결과를 출력합니다.
병렬 맵-리듀스
QtConcurrent::mappedReduced()는 QtConcurrent::mapped()와 유사하지만, 새로운 결과가 포함된 시퀀스를 반환하는 대신 리듀스 함수를 사용하여 결과를 단일 값으로 결합합니다.
리듀스 함수는 다음 형식을 따라야 합니다:
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 함수가 반환하는 각 결과에 대해 한 번씩 호출되며, 중간 결과를 result 변수에 병합해야 합니다. QtConcurrent::mappedReduced()는 한 번에 하나의 스레드만 reduce를 호출하도록 보장하므로, result 변수를 잠그기 위해 뮤텍스를 사용할 필요가 없습니다. QtConcurrent::ReduceOptions 열거형은 축소 연산이 수행되는 순서를 제어하는 방법을 제공합니다. QtConcurrent::UnorderedReduce 가 사용될 경우(기본값), 순서는 정의되지 않지만, QtConcurrent::OrderedReduce 를 사용하면 축소 연산이 원본 시퀀스의 순서대로 수행되도록 보장합니다.
추가 API 기능
Sequence 대신 Iterator 사용
위의 각 함수에는 시퀀스 대신 이터레이터 범위를 인수로 받는 변형이 있습니다. 이 함수들은 시퀀스 변형과 동일한 방식으로 사용합니다:
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 void computeAverage(int &average, int length);
QStringList strings =...;
QFuture<int> averageWordLength = QtConcurrent::mappedReduced(strings, &QString::length, computeAverage);
// 목록에 있는 모든 이미지의 색상 분포를 나타내는 집합을 생성합니다.
extern int colorDistribution(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();여러 인자를 받는 함수 래핑
두 개 이상의 인수를 받는 map 함수를 사용하려면 람다 함수나 ` std::bind() `를 사용하여 이를 하나의 인수를 받는 함수로 변환할 수 있습니다.
예를 들어, QImage::scaledToWidth()를 사용해 보겠습니다:
QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const;scaledToWidth는 세 개의 인자(`"this"` 포인터 포함)를 받으며, QtConcurrent::mapped()는 하나의 인자를 받는 함수를 기대하기 때문에 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.