在什么情况下,让两个不同的线程同时写入x86上相同阵列的相邻元素是不安全的?据我所知,在一些类似DS9K的体系结构中使用疯狂的内存模型会导致单词撕裂,但在x86单字节上是可寻址的。例如,在D编程语言中 real 是x86上的80位浮点类型。做类似的事情是否安全:

real[] nums = new real[4];  // Assume new returns a 16-byte aligned block.
foreach(i; 0..4) {
    // Create a new thread and have it do stuff and 
    // write results to index i of nums.
}

注意:我知道,即使这是安全的,它有时也会导致缓存共享错误,从而导致性能降低。但是,对于我想到的用例,写入的内容很少,实际上并不重要。

编辑:不要担心回读写入的值。假设在读取任何值之前同步。我只关心这种写作的安全性。

有帮助吗?

解决方案

x86具有连贯的缓存。写入高速缓存行的最后一个处理器获取整个事物并写入高速缓存。这可确保写入相应值的单字节和4字节值以原子方式更新。

这与“它的安全”不同。如果处理器每个只写入字节/ DWORDS“拥有”,则通过该处理器设计,然后更新将是正确的。实际上,您希望一个处理器读取其他人编写的值,这需要 同步。

它也不同于“有效”。如果多个处理器可以分别写入高速缓存行中的不同位置,则高速缓存行可以在CPU之间进行乒乓,这比高速缓存行转到单个CPU并保持在那里要贵得多。 通常的规则是将特定于处理器的数据放在其自己的缓存行中。 当然,如果你只想写一个单词,只需要一次,和 那么,与缓存行移动相比,工作量是显着的 你的表现是可以接受的。

其他提示

我可能会遗漏一些东西,但我没有预见到任何问题。 x86架构只写入它需要的内容,它不会在指定值之外进行任何写入。 Cache-snooping处理缓存问题。

您正在询问有关x86的详细信息,但您的示例是使用某种高级语言。关于D的具体问题只能由编写您正在使用的编译器的人员或D语言规范来回答。例如,Java要求数组元素访问不得导致撕裂。

关于x86,操作的原子性在英特尔软件开发人员手册第3A卷第8.1节中规定。 。根据它,原子存储操作包括:存储一个字节,在所有x86 CPU上存储字对齐字和双字对齐双字。它还指定在P6及更高版本的CPU上,对高速缓存行内的高速缓存内存的未对齐16位,32位和64位访问是原子的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top