我有10个线程Vec
,长度为100.
我可以在0-9元素(例如,排序它们)上使用线程0,而线程1正在处理元素10-19等等吗?
或者我必须使用Vec<Vec<>>
这个吗?(我宁愿避免,因为元素在内存中不再是连续的)
Lin*_*ope 10
是的你可以.你问过可变的情况,但我会先说,如果它Vec
是只读的(例如减少),你可以安全地向每个线程中你想要的特定切片发送一个不可变的引用.你可以通过简单地使用&my_vec[idx1..idx2]
循环中的东西来做到这一点.
对于可变的情况,它有点棘手,因为借用跟踪器不够复杂,不允许非重叠借用a Vec
.但是,有很多方法,特别是split_at_mut
你可以调用来获取这些子句.到目前为止最容易的是这里chunks_mut
记录的迭代器.(注意,对于不可变的情况,存在匹配的迭代器,因此在编写任何一种情况时只需要进行微小的更改).chunks
请注意,chunks
和chunks_mut
函数占用每个块的大小,而不是块的数量.但是,从另一个中获得一个是相当简单的.
不过,我想对可变的案例说几句话.如果均匀分割数据,可能会产生糟糕的性能.原因是CPU不能在单个地址上工作,而是在称为高速缓存行(64字节长)的内存块上工作.如果多个线程在单个高速缓存行上工作,则它们必须写入和读取较慢的内存,以确保线程之间的一致性.
不幸的是,在安全的Rust中,没有简单的方法来确定缓存行Vec
的缓冲区在哪里开始(因为缓冲区的启动可能已经分配在CPU缓存行的中间),我所知道的大多数方法都是为了检测这个涉及使用实际指针地址的低字节进行调整.处理此问题的最简单方法是在要使用的每个块之间添加一个64字节的无意义数据.因此,例如,如果你有一个Vec
包含1000个32位浮点数和10个线程,你只需在每个浮点数之间添加16个带有虚拟值的浮点数(因为32位= 4字节,16*4 = 64 = 1个高速缓存行) 100个你的"真实"花车并在计算过程中忽略假人.
这被称为虚假共享,我鼓励您查找其他参考资料,以了解处理此问题的其他方法.
请注意,x86体系结构保证了64字节的行大小.如果您正在编译ARM,PowerPC,MIPS或其他内容,则此值可能会有所不同.
归档时间: |
|
查看次数: |
460 次 |
最近记录: |