我有一个任务,从概念上简化为13M元素中的每个元素添加一个常数,25MB大小的数组,不适合20MB大小的缓存 . 因此,我的实现是迭代遍历数组索引的for循环 . 我使用英特尔线程构建模块(TBB)将英特尔至强E系列服务器上的任务与以下规范并行化:

20 CPUs Sandy Bridge Micro-architecture 32K L1D, 256K L2, 20M L3

有两种可能的并行化方案 . 一方面,我可以使用Intel TBB中的parallel_for模板函数来实现这一点,其中Block_range对象有助于将数组分解为块 . 另一方面,我可以选择手动将数组分成块,并将每个块调用一个任务,该任务可以传递给TBB的管道模式 .

令我惊讶的是,对于两种实现,使用Oprofile在固定块大小10000(大约L2高速缓存大小)下测量的执行时间显着不同 . 更简单的parallel_for函数以200MB / s处理,而更复杂的管道模式以600MB / s处理 . 对于parallel_for,改变grain_size(1,000,000到10,每次递减10倍 . )不会大大改变数据处理速率 . 改变流水线模式的chunk_size会改变处理速率,这些变化可以与L1,L2和L3缓存的大小相关联 .

我是否将parallel_for与错误的grain_size一起使用?或者管道固有地比parallel_for快?当手动和自动分割阵列时,通常建议使用parallel_for或pipeline吗?用管道替换parallel_for有什么优缺点?

谢谢,顾