zoukankan      html  css  js  c++  java
  • Qt 并行运算高级API QtConcurrent

    Qt Concurrent模块扩展了Qt Core模块中的基本线程支持,简化了可以在所有可用的CPU核心上并行执行的代码开发。

    一些常用API:

    • Concurrent Map 和 Map-Reduce

    QtConcurrent::map():将一个函数应用于一个容器中的每一项,就地修改 items。

    QtConcurrent::mapped():和 map() 类似,只是它返回一个包含修改内容的新容器。

    QtConcurrent::mappedReduced():和 mapped() 类似,只是修改后的结果减少或组合 成一个单一的结果。

    • Concurrent Filter 和 Filter-Reduce

    QtConcurrent::filter():从容器中删除所有满足某个条件的item。

    QtConcurrent::filtered():和 filter() 类似,只是它返回一个包含过滤内容的新容器。

    QtConcurrent::filteredReduced():和 filtered() 类似,只是过滤后的结果减少或组合成一个单一的结果。

    • Concurrent Run

    QtConcurrent::run():在另一个线程中运行一个函数。

    QFuture:表示异步计算的结果

    QFutureIterator:允许通过 QFuture 遍历可用的结果

    QFutureWatcher:允许使用信号槽来监控一个 QFuture

    QFutureSynchronizer:是一个方便的类,用于一些 QFutures 的自动同步

    Qt Concurrent 支持多种兼容 STL 的容器和迭代器类型,但是最好使用具有随机访问迭代器的 Qt 容器,例如:QList 或 QVector。map 和 filter 函数都接受容器和 begin/end 迭代器。

    在 Qt Concurrent 迭代大量轻量级 items 的情况下,随机访问迭代器可以更快,因为它们允许跳过容器中的任何点。此外,使用随机访问迭代器允许 Qt Concurrent 通过 QFuture::progressValue() 和 QFutureWatcher::progressValueChanged() 来提供进度信息。

    非就地修改的函数(例如:mapped() 和 filtered()),在调用时会创建容器的副本。如果正在使用的是 STL 容器,此复制操作可能需要一段时间,在这种情况下,建议为容器指定 begin 和 end 迭代器。

    Concurrent Map 和 Map-Reduce示例:

     1 void add(int &num)
     2 {
     3     num +=1;
     4 }
     5 
     6 int mappedReducedFunction(const int& num)
     7 {
     8     return num + 1;
     9 }
    10 
    11 void ReduceFunction(int& result, const int& item)
    12 {
    13     result = item > result ? item : result;
    14 }
    15 
    16 {
    17     QVector<int> vector;
    18 
    19     for(int i=0; i<3; i++)
    20        vector.append(i);
    21 
    22     qDebug() << "start: " << vector;
    23 
    24     QFuture<void> vFuture = QtConcurrent::map(vector, add);
    25     vFuture.waitForFinished();
    26 
    27     qDebug() << "map result: " << vector;
    28 
    29     QFuture<int> iFuture = QtConcurrent::mappedReduced(vector, mappedReducedFunction, ReduceFunction);
    30 
    31     qDebug() << "mappedReduced result: " << iFuture.result();
    32 }

    结果输出:

    start: QVector(0, 1, 2)
    map result: QVector(1, 2, 3)
    mappedReduced result: 4

    QtConcurrent::mappedReduced() 类似于 QtConcurrent::mapped(),但是不是返回具有新结果的序列,而是使用 reduce 函数将结果组合成单个值。

    reduce 函数必须是以下形式:

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

    T 是最终结果的类型,U 是 map 函数的返回类型。注意: reduce 函数的返回值、返回类型没有被使用。

    对于 map 函数返回的每个结果,reduce 函数将被调用一次,并且应该将中间体合并到结果变量中。QtConcurrent::mappedReduced() 保证一次只有一个线程调用 reduce,所以没有必要用一个 mutex 锁定结果变量。

    QtConcurrent::ReduceOptions 枚举提供了一种方法来控制 reduction 完成的顺序。如果使用 QtConcurrent::UnorderedReduce(默认),顺序是不确定的;而 QtConcurrent::OrderedReduce 确保 reduction 按照原始序列的顺序完成。

    Concurrent Filter Filter-Reduce 与 Concurrent Map Map-Reduce 使用基本一致。

    QtConcurrent::run() 函数在一个单独的线程中运行一个函数, 函数的返回值通过 QFuture API 提供。

    Concurrent Run示例:

     1 int add(int &num)
     2 {
     3      return ++num;
     4 }
     5 
     6 {
     7     QFuture<int> future = QtConcurrent::run(add, 1);
     8     future.waitForFinished();
     9 
    10     qDebug() << "result: " << future.result();
    11 }

    结果输出:

    result: 2

    上述两个示例中,我们都是QFuture阻塞线程等待计算完成;QFuture 还提供了很多方法与正在进行的异步调用进行交互。例如,使用 cancel() 函数取消计算;要暂停计算,使用 setPaused() 函数或 pause(),resume()、togglePaused() 便利函数之一。

    注意:并非所有异步计算都可以取消或暂停。例如,QtConcurrent::run() 返回的 future 不能被取消,但 QtConcurrent::mappedReduced() 返回的可以。

  • 相关阅读:
    zeplin 登录效果实现
    instanceof 是如何工作的
    JavaScript版—贪吃蛇小组件
    C#+HtmlAgilityPack—糗事百科桌面版V2.0
    Google自定义搜索引擎
    百度网盘资源搜索器
    CSS元素类型
    CSS盒子模型
    Android调用Web服务
    无法将匿名方法转换为System.Delegate
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14149888.html
Copyright © 2011-2022 走看看