并行模式库 (PPL) 提供命令式编程模型,以促进开发并发应用程序的可扩展性和易用性。 PPL 构建在并发运行时的计划和资源管理组件上。 通过提供并行作用于数据的泛型安全算法和容器,提高应用程序代码与基础线程机制之间的抽象级别。 使用 PPL 还可以开发通过为共享状态提供替代方案实现缩放的应用程序。
PPL 提供以下功能:
任务并行:基于 Windows 线程池来并行执行多个工作项(任务)的机制
并行算法:基于并发运行时对数据集合进行处理的泛型算法
并行容器和对象:对元素提供安全并发访问的泛型容器类型
这是MSDN上对PPL的介绍,可以看出,PPL是基于线程池模型的,主要是为了在并行编程中屏蔽底层特性。
并行迭代
concurrency::parallel_for 算法重复地以并行方式执行相同的任务。 其中每个任务都由迭代值进行参数化。 当一个循环体不在该循环的各个迭代之间共享资源时,此算法很有用。
parallel_for 算法会按照最佳方式对任务进行分区以便并行执行。 当工作负载不平衡时,此算法还会使用工作窃取算法和范围窃取来平衡这些分区。 当以协作方式阻止某个循环迭代时,运行时会将指派给当前线程的迭代范围重新发布给其他线程或处理器。 类似地,当某个线程完成迭代范围时,运行时会将其他线程的工作重新发布给该线程。 parallel_for 算法还支持嵌套并行。 当一个并行循环包含另一个并行循环时,运行时会以一种适合并行执行的高效方式在循环主体之间协调处理资源。
parallel_for是for语句的并行版本,基于整数的循环迭代。
parallel_for_each用于STL迭代器的迭代。
在并行循环中,PPL会用多种标准来对循环规模进行拆分,然后将拆分后的每个循环投递到相应的Worker线程中,同时还会进行负载均衡,当然这些都是线程池的机制。
函数体:
void parallel_for(_Index_type _First, _Index_type _Last, _Index_type _Step, const _Function& _Func, _Partitioner&& _Part)
其中Step是步长,Func是执行迭代的函数,Part是用于确定怎样拆分的函数。
拆分函数:
- auto_partitioner
这个函数简单的以虚拟处理器数为基准进行拆分:
虚拟处理器是PPL对资源管理的一个抽象概念,通常不会超过处理器线程数。
_Type _Get_num_chunks(_Type ) const
{
return static_cast<_Type>(Concurrency::details::_CurrentScheduler::_GetNumberOfVirtualProcessors());
}
- affinity_partitioner
这个函数使循环的拆分同时考虑了虚拟处理器和硬件特性
_Type _Get_num_chunks(_Type )
{
if (_M_num_chunks == 0)
{
_M_num_chunks = Concurrency::details::_CurrentScheduler::_GetNumberOfVirtualProcessors();
_M_pChunk_locations = new location[_M_num_chunks];
}
return static_cast<_Type>(_M_num_chunks);
}
location是对物理环境的抽象
- simple_partitioner
按指定的长度平均拆分。
_Type _Get_num_chunks(_Type _Range_arg) const
{
static_assert(sizeof(_Type) <= sizeof(_Size_type), "Potential truncation of _Range_arg");
_Size_type _Num_chunks = (static_cast<_Size_type>(_Range_arg) / _M_chunk_size);
if (_Num_chunks == 0)
{
_Num_chunks = 1;
}
return static_cast<_Type>(_Num_chunks);
}
如果有需要也可以按照自己的要求进行拆分,