Qt Concurrent 并发 Map 和 Map-Reduce

并发 Map 和 Map-Reduce

  • QtConcurrent::map()会对容器中的每个项目应用一个函数,对项目进行就地修改。
  • QtConcurrent::mapped() 类似于 map(),但它返回的是一个包含修改内容的新容器。
  • QtConcurrent::mappedReduced() 类似于 mapped(),只不过修改后的结果被缩小或折叠成一个结果。

上述每个函数都有一个阻塞变体,它返回最终结果而不是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)。

并发 Map

QtConcurrent::mapped() 接收一个输入序列(=容器)和一个映射函数。然后,序列中的每个项目都会调用该映射函数,并返回一个包含映射函数返回值的新序列。

映射函数的形式必须是

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-Reduce

QtConcurrent::mappedReduced() 类似于 QtConcurrent::mapped(),但不是返回包含新结果的序列,而是使用 reduce 函数将结果合并为一个值。

reduce 函数的形式必须是

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

T 是最终结果的类型,U 是映射函数的返回类型。注意,不使用 reduce 函数的返回值和返回类型。

像这样调用 QtConcurrent::mappedReduced():

QImage scaled(const QImage &image)
{return image.scaled(100, 100);
}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);

map 函数返回的每个结果都将调用一次 reduce 函数,并将中间 结果合并到结果变量中。QtConcurrent::mappedReduced() 保证每次只有一个线程调用 reduce,因此无需使用互斥来锁定结果变量。QtConcurrent::ReduceOptions 枚举提供了一种控制还原顺序的方法。如果使用QtConcurrent::UnorderedReduce (默认值),则顺序未定义,而QtConcurrent::OrderedReduce 可确保按照原始序列的顺序进行还原。

其他应用程序接口功能

使用迭代器代替序列

上述每个函数都有一个使用迭代器范围而非序列的变体。使用方法与序列变体相同:

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() 接受指向成员函数的指针。成员函数类的类型必须与存储在序列中的类型相匹配:

// Squeeze all strings in a QStringList.
QStringList strings = ...;
QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);// Swap the rgb values of all pixels on a list of images.
QList<QImage> images = ...;
QFuture<QImage> bgrImages = QtConcurrent::mapped(images,static_cast<QImage (QImage::*)() const &>(&QImage::rgbSwapped));// Create a set of the lengths of all strings in a list.
QStringList strings = ...;
QFuture<QSet<int>> wordLengths = QtConcurrent::mappedReduced(strings, &QString::length,qOverload<const int&>(&QSet<int>::insert));

注意qOverload 的使用。需要使用它来解决有多个重载的方法的歧义问题。

还请注意,在使用 QtConcurrent::mappedReduced() 时,您可以自由混合使用普通函数和成员函数:

// Can mix normal functions and member functions with QtConcurrent::mappedReduced().// Compute the average length of a list of strings.
extern void computeAverage(int &average, int length);
QStringList strings = ...;
QFuture<int> averageWordLength = QtConcurrent::mappedReduced(strings, &QString::length, computeAverage);// Create a set of the color distribution of all images in a list.
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));

还原函数也支持函数对象:

struct ImageTransform
{void operator()(QImage &result, const QImage &value);
};QFuture<QImage> thumbNails =QtConcurrent::mappedReduced(images, Scaled(100), ImageTransform(),QtConcurrent::SequentialReduce);

使用 Lambda 表达式

QtConcurrent::map()、QtConcurrent::mapped()和 QtConcurrent::mappedReduced() 接受 map 和 reduce 函数的 lambda 表达式:

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() 时,您可以自由混合使用普通函数、成员函数和 lambda 表达式

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

您还可以将 lambda 传递给 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 函数,可以使用 lambda 函数或std::bind() 将其转换为一个包含一个参数的函数。

例如,我们将使用 QImage::scaledToWidth():

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

scaledToWidth 需要三个参数(包括 "this "指针),并且不能直接与 QtConcurrent::mapped() 一起使用,因为 QtConcurrent::mapped() 期望使用一个参数的函数。要在 QtConcurrent::mapped() 中使用 QImage::scaledToWidth(),我们必须提供宽度值和转换模式

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

Concurrent Map and Map-Reduce | Qt Concurrent 6.8.2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RT-Thread-线程管理

一、线程管理 RT_Thread线程管理主要是实现线程管理和调度&#xff0c;线程分为用户线程和系统线程。RT_Thread的线程调度器是抢占式的&#xff0c;寻找就绪状态最高优先级线程。 线程管理的API函数 创建线程函数 rt_thread_t rt_thread_create( const char *name, //线程名称 …

【CC2530 教程 十二】CC2530 Z-Stack 硬件抽象层

目录 一、硬件抽象层简介&#xff1a; &#xff08;1&#xff09;HAL 硬件抽象层是什么&#xff1f; &#xff08;2&#xff09;通俗易懂的解释&#xff1a; &#xff08;3&#xff09;具体例子&#xff1a; 二、硬件抽象层HAL&#xff1a; &#xff08;1&#xff09;HAL…

Linux如何判断磁盘是否已分区?

在 Linux 系统中&#xff0c;判断磁盘是否已分区可通过以下方法实现&#xff1a; 方法 1&#xff1a;使用 fdisk -l 命令 此命令会列出所有磁盘及其分区的详细信息&#xff1a; sudo fdisk -l输出解读&#xff1a; 若磁盘&#xff08;如 /dev/sdb&#xff09;下有类似 /dev/…

《熔化焊接与热切割作业》考试注意事项

考试前的准备 携带必要的证件和材料&#xff1a;考生需携带身份证、准考证等有效证件&#xff0c;以及考试所需的焊接工具、材料等。确保证件齐全&#xff0c;避免因证件问题影响考试。 提前检查焊接设备和工具&#xff1a;在考试前&#xff0c;考生应仔细检查焊接设备和工具是…

Matlab Hessian矩阵计算(LoG算子)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 图像的Hessian矩阵用于描述图像灰度值的二阶导数,可以用来分析图像的局部曲率和变化。例如,在图像边缘检测、特征点检测等任务中,Hessian矩阵能帮助我们识别图像的结构。 Hessian矩阵定义 对于二维图像,Hessian…

selenium之处理弹框(alert、confirm、prompt)

弹框 WebDriver提供了一个API, 用于处理JavaScript提供的三种类型的原生弹窗消息. 这些弹窗由浏览器提供限定的样式.&#xff1b;分别为以下三种 alerts警告框confirm确认框prompt提示框 话不多说&#xff0c;开始实践下就知道怎么一回事了 alerts 警告框&#xff0c;显示…

Visual Studio 2019 Qt QML 项目环境搭建常见问题处理方法

在 Visual Studio 2019 运行 Qt/QML 项目比直接使用QtCreator环境麻烦&#xff0c;主要是有qmake 的一些配置项不能在 Visual Studio中设置。下面整理一些常见问题的处理方法&#xff0c;供参考&#xff1a; 搭建VS Qt 环境&#xff0c;在Visual Studios 2019下面安装 Qt Vis…

【Linux】POSIX信号量与基于环形队列的生产消费者模型

目录 一、POSIX信号量&#xff1a; 接口&#xff1a; 二、基于环形队列的生产消费者模型 环形队列&#xff1a; 单生产单消费实现代码&#xff1a; RingQueue.hpp&#xff1a; main.cc&#xff1a; 多生产多消费实现代码&#xff1a; RingQueue.hpp&#xff1a; main.…

RAG优化:python从零实现GraphRag 一场文档与知识的“恋爱”之旅

嘿,亲爱的算法工程师们,准备好迎接一场文档与知识的“恋爱”之旅了吗?今天我们要介绍的 Graph RAG,就像是一位“红娘”,帮助文档和知识在图的世界里找到彼此,擦出智慧的火花! 文章目录 为什么需要 Graph RAG?Graph RAG 的“恋爱秘籍”准备好了吗?让我们开始吧!环境设…

深入 SVG:矢量图形、滤镜与动态交互开发指南

1.SVG 详细介绍 SVG&#xff08;Scalable Vector Graphics&#xff09; 是一种基于 XML 的矢量图形格式&#xff0c;用于描述二维图形。 1. 命名空间 (Namespace) ★ 了解 命名空间 URI&#xff1a;http://www.w3.org/2000/svg 用途&#xff1a;在 XML 或 XHTML 中区分不同标…

HTTPS 加密过程详解

HTTPS 的核心组成是 HTTP 协议与 SSL/TLS 加密层的结合&#xff0c;通过加密传输、身份验证和完整性校验机制&#xff0c;确保数据安全。其加密过程通过以下方式保障数据的机密性、完整性和身份验证&#xff1a; 一、HTTPS 的核心组成 1. HTTP 协议 作为基础通信协议&#xf…

嵌入式硬件工程师从小白到入门-速通版(一)

嵌入式硬件工程师从小白到入门&#xff1a;知识点速通与实战指南 一、基础硬件知识体系 电子电路基础 基本概念&#xff1a;电流、电压、电阻、电容、电感等&#xff1b;电路分析&#xff1a;欧姆定律、基尔霍夫定律、戴维南定理&#xff1b;元器件特性&#xff1a;二极管、三极…

SpringBoot通过Map实现天然的策略模式

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; SpringBoot通过Map实现天然的策略模式 ⏱️ 创作时间&#xff1a; 202…

WordPress WooCommerce 本地文件包含漏洞(CVE-2025-1661)

免责声明 仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 一:产品介绍 HUSKY – WooCommer…

matlab近似计算联合密度分布

在 Matlab 中&#xff0c;当A和B是两个序列数据时&#xff0c;可以通过以下步骤来近似求出A大于B的概率分布&#xff1a;数据准备&#xff1a;确保序列A和B具有相同的长度。如果长度不同&#xff0c;需要进行相应的处理&#xff08;例如截取或插值&#xff09;。计算A大于B的逻…

可视化动态表单动态表单界的天花板--Formily(阿里开源)

文章目录 1、Formily表单介绍2、安装依赖2.1、安装内核库2.2、 安装 UI 桥接库2.3、Formily 支持多种 UI 组件生态&#xff1a; 3、表单设计器3.1、核心理念3.2、安装3.3、示例源码 4、场景案例-登录注册4.1、Markup Schema 案例4.2、JSON Schema 案例4.3、纯 JSX 案例 1、Form…

NAT 实验:多私网环境下 NAPT、Easy IP 配置及 FTP 服务公网映射

NAT基本概念 定义&#xff1a;网络地址转换&#xff08;Network Address Translation&#xff0c;NAT&#xff09;是一种将私有&#xff08;保留&#xff09;地址转化为合法公网 IP 地址的转换技术&#xff0c;它被广泛应用于各种类型 Internet 接入方式和各种类型的网络中。作…

C语言-桥接模式详解与实践

文章目录 C语言桥接模式详解与实践1. 什么是桥接模式&#xff1f;2. 为什么需要桥接模式&#xff1f;3. 实际应用场景4. 代码实现4.1 UML 关系图4.2 头文件 (display_bridge.h)4.3 实现文件 (display_bridge.c)4.4 使用示例 (main.c) 5. 代码分析5.1 关键设计点5.2 实现特点 6.…

el-table 合并单元格

vue2使用el-table合并单元格&#xff0c;包括合并行、合并列 <el-table:header-cell-style"handerMethod":span-method"arraySpanMethod"cell-click"handleCellClick":data"tableData"style"width: 100%"><el-tabl…

网络安全之vlan实验

在对vlan进行一定的学习之后我们来练习一个小实验来加深理解记忆 首先是对实验进行一个搭建 第一部分&#xff1a;给交换机配置vlan 首先是sw1 [Huawei]vlan batch 2 to 5 [Huawei]int g0/0/1 [Huawei-GigabitEthernet0/0/1]port hybrid tagged vlan 2 [Huawei-GigabitEthe…