Visual C++本地并行编程中的状态管理 |
使命组 取缔 新的Beta1 PPL的其中一个 性能便是 可以 取缔正在运行中的 使命组 。在task_group类型上加入run 和 wait 步骤是一个新的cancel 步骤 。还有一个相应的is_canceling 步骤让你 可以 审查在 历程中是不是 实现 取缔 。task_group_status列举也有一个新的值叫做canceled,让你 审查 取缔是不是 产生 。以下的代码 展示了这些新的 性能: //declare tasks and run tasks task_group tg; tg.run(([]{printf("consoleWrite0\n");})); tg.run(([]{printf("consoleWrite1\n");})); //cancel tasks tg.cancel(); //check whether tasks are being cancelled bool taskGroupIsCanceling = tg.is_canceling(); //check on status of task group task_group_status status = tg.wait(); if (status == completed){ printf("Tasks were completed successfully\n"); } else if (status == canceled){ printf("Tasks were canceled during task execution\n"); } else{ printf("An exception occured during task execution\n"); } Combinable 类型 达到并行执行编程 使命的最大利益的有效 模式之一是工作在当地拷贝或是子数据上的每一个并行分支被 解决, 而后当 解决 完毕后,将 后果合并 。这个 模式 可以最大限度的削减资源争用,并且削减潜在的死锁和当并行线程试图更新 雷同的内存位置时所 产生的数据不 统一的问题 。 使用这个 模式没有那么复杂,然而需求很乏味的为每一个 使用进行手动编码 。为了简化 模式 使用,Visual C++ 2010 Beta 1 增加了combinable模版类型 。这个模版参数传递到combinable是每个 使命将要操作的对象类型 。这个类型必须有一个默许的 构造器和一个拷贝 构造器 。通过 使用local 步骤,每个 使命 拜访它自己的combinable治理资源的拷贝 。 当全部 使命 完毕后,通过 使用combine 或是 combine_each 步骤,你 可以将全部 后果合并到一个 后果集中 。 以下的代码用三个独立的 使命增加一些元素给一个矢量, 而后用两个合并的 步骤将 后果合并成一个矢量 。 //declare a combinable vector of integers combinable< vector< int>> v; //add an element to the vector using three separate tasks parallel_invoke( [&]{ v.local().push_back(1); }, [&]{ v.local().push_back(2); }, [&]{ v.local().push_back(3); } ); //merge the task-local copies using combine_each vector< int> result1; v.combine_each( [&](vector< int>& local) { result1.insert(result1.end(), local.begin(), local.end()); } ); //merge the task-local copies using combine vector< int> result2 = v.combine( [](vector< int> left, vector< int> right)->vector< int>{ left.insert(left.end(), right.begin(), right.end()); return left; }); 要 留神的是在最终一行的代码语句中的lambda 抒发式的明确返回类型申明的 使用 。在lambda 抒发式中的两个语句阻挠编译器正确判断返回类型,所以需求手动申明 。 也 可 认为没有默许 构造器(或是在众多状况下默许 构造器的 使用是不 合适的)的类型 使用combinable,通过 使用combinable 构造器,它是采纳了一个 产生器 性能 缔造了一些模版参数类型的对象 。上面代码的前面几行是 使用超载 产生器 构造器而再一次编写的 。在这种状况下, 产生器 性能返回已经包括一个元素的矢量 。 //declare a combinable vector of integers inable< vector< int>> v([]{return vector< int>(1, 0);}); 同步 Combinable的 使用取决于不需求作用在 其余 使命上的 后果的 使命 。在多重 使命的状况下需求分享一个对象,你必须 使用更传统的同步策略 。PLL 本身带有三个同步原语——critical_section, reader_writer_lock 和 event 。critical_section锁住内存位置 预防没有锁的全部 使命的 拜访 。关于内存位置将有众多同时读取者和少数编写者,更优化的reader_writer_lock是可用的,同意多重读取者猎取锁并同时 拜访内存位置 。最终的原语是event,用于在 使命和线程中间发信号 。 同步原语在concrt.h 题目文件(是PPL的 根本 题目文件,包括在ppl.h中)中被定义 。在concrt.h中定义的大多数类型的 指标是图书馆作者,而不是 利用程序的开发者,然而任何对深层并行开发有兴趣的人都 可以 自由的 考查和 使用 适当的来自 袒露在外的类型的 性能 。 critical_section类型的API是十分 方便的;你 使用一个blocking lock 步骤来猎取这个锁,non-blocking try_lock会试图去猎取这个锁,假如它可用的话,并且unlock会 开释一个锁住的critical_section 。 reader_writer_lock是有丝毫点的复杂 。它增加了两个 步骤,lock_read 和try_lock_read, 可以 支撑猎取一个reader lock 。Unlock 步骤和critical_section是一样的,并且将 开释 适当的基于锁类型的锁 。 最终的同步原语是event,这是手动复位事件(即:事件 维持设置直到用外部代码进行手动复位) 。代码 可以通过调用实例wait 步骤(也是 支撑一个可选的timeout值),期待一个单一事件被设置 。当没有timeout被定义的时候,期待的 工夫是无限的 。你 可以期待多重事件,通过 使用静态wait_for_multiple,它 承受C-style的event pointers 。wait_for_multiple 步骤期待一个单一事件或是全部的事件传递到 步骤调用 。以下的代码期待这两个事件被设置: event* events[2]; events[0] = new event(); events[1] = new event(); parallel_invoke( [&]{ events[0]->set(); }, [&]{ events[1]->set(); } ); bool waitForAllEvents = true; event::wait_for_multiple(events, 2, waitForAllEvents); 当同时执行众多 使命的时候, 解决状态治理是十分艰巨的工作 。PPL提供对状态治理的一种 模式的 支撑,便是每个线程在当地版本的分享对象上进行操作,在程序 完毕的时候将这些 后果合并起来 。关于 拆散状态治理的状况是不 适当的,PPL以critical_section, reader_writer_lock 和 event的 模式提供传统的同步原语 。 |