Visual Studio 11开发指南(19)C++11更新-并行模式库和代理库

最后更新于:2022-04-01 10:27:32

 Visual Studio 11,具备并行模式库和代理库、 更轻松地开发多核处理器上运行的并行代码。 这些库的主要范例是根据任务 和并发运行库,自定义的调度程序 进行处理的。 到目前为止,处理任务的的概念原型,就使用task_handle 类型 如下所示: ~~~ task_group task; int i=0; auto t1=make_task([&i]() { i=42; }); int z=0; auto t2=make_task([&z]() { z=42; }); task.run_and_wait (t1); task.run_and_wait (t2); std::wcout << i+z << std::endl; std::wcout << "Fini" << std::endl; ~~~ 这里计算的 i + z 是必须得到的 lambda 表达式中引用变量 。然后这两个任务并行完成它们的工作。 使用 Visual Studio 11,可以直接使用的task类型的概念,如下所示: ~~~ task<int> t1=task<int>(->int { return 42; }); task<int> t2=task<int>(->int { return 42; }); std::wcout << t1.get() +t2.get () << std::endl; ~~~ 为了简化语法,更需要为每项任务捕获变量的引用,要通过调用方法wait()的每个任务并返回值角色的方法get (),获取状态以便处理 。 task类的异步任务的遵循设置的运行规则,无需等待,即是说,不论Tn 取决于 Tn-1 任务的任务以及前一任务已完成或没有。 异步操作将概括为避免假死的用户界面,很重要的是为了简化开发过程,以前的VS经常卡死,加载控件的时候。 若要实现这一概念,task类实现的then()方法,将会执行一次已经完成后的该任务。 ~~~ task<int> t1=task<int>(->int { return 42; }).then ([](int i)->int { return i+42; }); task<int> t2=task<int>(->int { //simule une charge std::this_thread::sleep_for (chrono::seconds (1)); return 42; }).then ([](int i)->int { return i+42; }); std::wcout << t1.get() + t2.get() << std::endl; ~~~ 每项任务的返回值是作为参数传递,例如lambda 表达式中的then()方法。 并行算法还包括 (parallel_for、 parallel_for_each、 parallel_invoke )) 并行算法的尝试 parallel_sort 、 parallel_radixsort、 parallel_buffered_sort的标准如果命令它只运行并行模式,其中使用算法的方式都相同。 ~~~ vector<unsigned int> v3; parallel_sort(begin(v3),end(v3)) ~~~ 虽然在大多数情况下,这是一个简单的类整数的性能足够流畅了(示例矢量的整数 40 000 000,得到一个序列(std::sort)和parallel_sort(),允许更好地调控,会提高性能) 每种算法,都用来做重载,这个方法允许设置的字符串的排序和要使用的分区的大小。 ~~~ vector<unsigned int> v2; parallel_sort(begin(v2),end(v2),[](const unsigned int& l,const unsigned int& r)->bool { return (l<r); },4096); ~~~ 默认分区大小为 2048,对于大多数情况下就足够了。可以调整最后一个分区的大小来提高性能。如果分区大小《=向量的大小,将使用任何方法std::sort ()中。(默认情况下,如果向量的元素的数目 < = 2048总是使用std::sort ()版本)。 ~~~ inline void parallel_sort(const _Random_iterator &_Begin, const _Random_iterator &_End, const _Function &_Func, const size_t _Chunk_size = 2048) { _CONCRT_ASSERT(_Chunk_size > 0); // We make the guarantee that if the sort is part of a tree that has been canceled before starting, it will // not begin at all. if (is_current_task_group_canceling()) { return; } size_t _Size = _End - _Begin; size_t _Core_num = Concurrency::details::_CurrentScheduler::_GetNumberOfVirtualProcessors(); if (_Size <= _Chunk_size || _Core_num < 2) { return std::sort(_Begin, _End, _Func); } _Parallel_quicksort_impl(_Begin, _Size, _Func, _Core_num * _MAX_NUM_TASKS_PER_CORE, _Chunk_size, 0); 21.} ~~~ 系统至少不会以任何方式使用 std::sort () 的虚拟处理器。 可用其他算法的尝试并根据实际需要。例如,在例子中的是基数排序 ~~~ vector<unsigned int> v4; parallel_radixsort(begin(v4),end(v4)); ~~~ 提供更好的结果 197.09 上 40 000 000 个项目。默认分区大小为 256 * 256 parallel_buffered_sort给 631 ~~~ parallel_buffered_sort(begin(v5),end(v5)); ~~~ 减少 线程申请的数量,最小,最多的一组所有成员称为一般减少。应用减少并行可以或者涉及争用条件或问题的另外的浮点操作的舍入为例。 例如双平行处理的循环,循环的量的一种方法是使用concurrency::combinable <T>对象 ~~~ combinable<double> sumReduction; parallel_for_each(begin(v1),end(v1),[&sumReduction](double i) { sumReduction.local ()+=i; }); sum=sumReduction.combine (std::plus<double>()); ~~~ Visual Studio 11,现在可以使用算法parallel_reduce(),比类型算法的使用效率更高(concurrency::combinable)。 它的使用是相对处理算法( std::accumulate) ~~~ vector<double>::const_iterator deb=begin(v1); vector<double>::const_iterator fin=end(v1); auto identity=std::iterator_traits<vector<double>::const_iterator>::value_type(); sum= parallel_reduce(deb,fin,identity,std::plus<double>()); ~~~ 转型 最后的算法是加工**parallel_transformation()**算法 ~~~ parallel_transform(begin(v1),end(v1),begin(v2),[](double value)->double { return value*2; }); ~~~ 赶紧下载VS11体验吧 [http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200098144](http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200098144)
';