使用并行化填充std::vector为零

7
我想用openmp快速将一个std::vector<int>填充为零。如何做到呢?
我听说循环遍历向量并将每个元素设置为零的方法很慢,而使用std::fill则要快得多。现在这个说法还正确吗? 将std::vector<int>的每个值重置为0的最快方法 我需要手动将std::vector<int>分成区域,使用#pragma omp for循环遍历每个线程,然后在循环中使用std::fill吗?

1
是的,这仍然是真的。如果您正在使用OpenMP,则必须自己分配作业。无论您采取哪种方式,如果您关心它的速度,您应该进行测量。我建议分配2的幂次方大小的作业(线程引用说它在MMX寄存器中使用了16个int,这可能是最小可行的作业大小)。根据向量的长度,单线程填充可能更快。一定要测量并找到交叉点。这是一条注释,因为它实际上不能很好地回答您的问题。这只是您自己可能会想到的思考。 - OmnipotentEntity
1
GCC 6.3和Clang 3.9.0都将“循环并将0赋值到每个位置”和std::fill编译成一个(尾)调用memset。虽然代码不完全相同,但是主要逻辑是相同的。 - harold
4
我敢打赌,用零填充向量只占用了你时间的一小部分。除非你有证据表明这是问题所在,否则不要担心它。 - Martin Bonner supports Monica
1
@voo,这是一个“我太心急了,没有测试”的编译器。这就是为什么你应该总是进行测试的原因。现在请原谅我,我得继续自我反省。 - OmnipotentEntity
1
@sbabbi,这只是将实际工作推迟到以后。可能由于局部性而有好处,但也可能对所有页面错误产生不良影响。 - Zulan
显示剩余7条评论
1个回答

7

您可以将向量分成块,每个线程用std::fill填充:

#pragma omp parallel
{   
    auto tid = omp_get_thread_num();
    auto chunksize = v.size() / omp_get_num_threads();
    auto begin = v.begin() + chunksize * tid;
    auto end = (tid == omp_get_num_threads() -1) ? v.end() : begin + chunksize);
    std::fill(begin, end, 0);
}

您可以通过将chunksize取近似缓存行/内存字大小(128字节= 32 int)来进一步改善它。假设v.data()也被类似地对齐,那么您就可以避免任何错误共享问题。
在一个双套接字24核Haswell系统上,我得到了约9倍的加速:1个线程需要3.6秒,而24个线程只需要0.4秒,4.8B个整数=每秒约48 GB的吞吐量。结果可能略有不同,这不是一项科学分析。但它与系统的内存带宽相差不远。
为了实现良好的性能,除了此操作之外,还应考虑将向量分隔为尽可能相同的部分以进行进一步的操作(无论是读取还是写入)。这样,您就可以增加数据实际上在缓存中的机会,或者至少位于同一NUMA节点上。
奇怪的是,在我的系统上,单线程的std::fill(..., 1);std::fill(..., 0)更快,但24个线程则更慢。都是使用gcc 6.1.0和icc 17.0.1时发生的。我想我会将其发布到单独的问题中。

乍一看,当向量的大小不能被线程数量整除时,这似乎不是最佳的计算线程划分。最后一个线程可能要做比其他线程少的工作。虽然感谢提供了 omp parallel 的好例子,但我不知道我们可以以那种方式使用 tid,在我的代码中仍然需要循环所有线程... - hamster on wheels
最后一个线程会得到更多的工作,但最多只有 nthreads - 1 的数量级,可以忽略不计。或者你可以使用 chunksize = (v.size() - 1) / nthreads + 1,这样更加平衡一些。但我认为(我要去编辑一下),更重要的是对齐块。 - Zulan
嗯,我现在明白了。 - hamster on wheels
我认为定义块可能会因舍入误差而导致问题,所以我会使用begin= ithread*N/nthreads, end = (ithread+1)*N/nthreads的方式,其中N=v.size()。这样可以在除法之前完成乘法运算。 - Z boson
@Zboson 我的观点是,nthreads-1 的最坏情况舍入误差微不足道,但将chunksize对齐到缓存行的可能性很重要。 - Zulan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接