Concurrency D并发写入缓冲区
假设您有一个大小为N的缓冲区,必须将其设置为确定值(例如设置为零或其他值)。缓冲区中的该值设置被划分为M个线程,每个线程处理缓冲区的N/M个元素 缓冲区不能是不可变的,因为我们更改了值。消息传递也不起作用,因为禁止传递ref或数组(=指针)类型。所以它必须通过Concurrency D并发写入缓冲区,concurrency,buffer,d,Concurrency,Buffer,D,假设您有一个大小为N的缓冲区,必须将其设置为确定值(例如设置为零或其他值)。缓冲区中的该值设置被划分为M个线程,每个线程处理缓冲区的N/M个元素 缓冲区不能是不可变的,因为我们更改了值。消息传递也不起作用,因为禁止传递ref或数组(=指针)类型。所以它必须通过共享?不,因为在我的例子中,缓冲区元素的类型是creal,因此算术不是原子的 最后,主程序必须等待所有线程完成。假设每个线程只写入数组的一个子集,并且数组中没有任何线程与另一个线程重叠,或者以任何方式相互依赖 如何以并发方式写入(或修改)缓
共享?不,因为在我的例子中,缓冲区元素的类型是creal
,因此算术不是原子的
最后,主程序必须等待所有线程完成。假设每个线程只写入数组的一个子集,并且数组中没有任何线程与另一个线程重叠,或者以任何方式相互依赖
如何以并发方式写入(或修改)缓冲区
PS:有时我可以简单地将数组分成M个连续的部分,但有时我会逐列遍历数组(数组是1D的,但表示2D数据)。这使得线程使用的单个数组实际上在母数组中交错。啊
编辑:我发现类型shared(creal)[
可以工作,因为现在元素是共享的,而不是数组本身。我打赌你可以并行交错阵列。但也有一些缺点:
shared
存储类非常严格,因此必须为分配提供关键字。这使得它很难被封装;由于调用者必须提供数组,因此它必须传递一个共享的数组,而不能只是一般地传递一个常规数组,让处理函数担心并行性。不,调用函数也必须考虑并行性,以便处理函数接收共享数组,而无需将数组重新分配到共享的空间
还有一个非常奇怪的bug,当我在某些位置动态分配shared(creal)[
时,它只是挂起在分配位置。看起来很随意,找不到罪犯。。。
在测试示例中,这是可行的,但在我的项目中不是。。。这原来是DMD/OptLink中的一个bug
EDIT2:我从来没有提到过,但它是用于实现FFT(快速傅立叶定理)。因此,我无法选择精确的缓存对齐切片。我只知道元素是creal类型,元素的数量是2的幂(每行/每列)。您可以使用该模块
但是如果你想重新发明它,你可以使用shared(只允许一个线程同时访问某个元素是线程安全的,如果你用合适的join()
或Task.*force()
更好)你尝试的听起来更像是并行而不是并发。您可以查看std.parallelism:只是一个元注释:如果阵列上的读/写是一个可能的瓶颈,请尝试调整切片大小,使其与缓存线边界对齐。否则,线程将相互碰撞缓存,您可能会看到明显的性能下降。@gmfawcett:或者,更简单地说,只需将工作单元设置得足够大,使线程之间共享的缓存线只占所用缓存线总数的一小部分。您能传递一条包含数组切片的消息吗?脏类型转换可以让您在需要时破坏类型系统。事实证明,并行和并发std LIB都可以用于此问题。
T[] buff;
foreach(ref elem;parallel(buff))elem=0;