假设您有一个大小为N的缓冲区,必须将其设置为确定值(比如说零或其他)。缓冲区中的此值设置被划分为M个线程,每个线程处理缓冲区的N / M个元素。
缓冲区不能是immutable
,因为我们更改了值。消息传递也不会起作用,因为禁止传递ref或array(= pointer)类型。所以它必须通过shared
发生?不,因为在我的情况下,缓冲区元素是creal
类型,因此算术不是原子的。
最后,主程序必须等到所有线程都完成。假设每个线程只写入数组的一个子集,并且没有任何线程在数组中与另一个线程重叠或以任何方式依赖于彼此。
我如何以并发方式写入(或修改)缓冲区?
PS:有时我可以简单地将数组分成M个连续的部分,但有时我会逐列遍历数组(数组是1D但代表2D数据)。这使得线程使用的各个阵列实际上在母阵列中交错。哎呀。
编辑:我发现类型shared(creal)[]
可以工作,因为现在元素是共享的而不是数组本身。你可以并行化交错的数组。但是有一些缺点:
shared
存储类非常严格,必须使用关键字提供分配。这使得它几乎不被封装;由于调用者必须提供数组,因此必须传递shared
数组,并且不能只传递常规数组并让处理函数担心并行性。不,调用函数也必须担心并行性,以便处理函数接收共享数组,并且不需要将数组重新分配到shared
空间。
还有一个非常奇怪的错误,当我在某些位置动态分配 这是DMD / OptLink中的一个错误。 shared(creal)[]
时,它只会在分配时挂起。似乎非常随意,无法找到罪魁祸首......
在测试示例中,这可行,但不适用于我的项目......
EDIT2:我从未提及过,但它实现了FFT(快速傅里叶定理)。所以我没有权力选择精确的缓存对齐切片。我所知道的是元素是creal类型,元素数量是2的幂(每行/列)。
答案 0 :(得分:2)
您可以使用std.parallelism模块
T[] buff;
foreach(ref elem;parallel(buff))elem=0;
但是如果你想重新发明这个,你可以只使用共享(这是线程安全的,只允许1个线程访问某个元素,如果你使用相应的join()
或{{1}强制执行此操作这太好了)