在四核机器上,我正在考虑C#/ .NET算法的并行化,它涉及让多个线程同时读取小型int []数组。到目前为止,它似乎运行得相当好,但我不确定在哪里指定数组上的并发读取在.NET中是线程安全的。有什么指针吗?
然后,我也想知道这种方法是否真的有效?有没有你最好实际复制每个线程的输入数据的情况,这样就没有任何并发读取,并且每个数组(可能?)都有机会在亲和CPU附近缓存?
有关多核CPU的最佳实践的想法吗?
答案 0 :(得分:18)
我不认为并发读取存在问题。但是,如果存在并发写入,则可能会出现问题。
不可变数据本质上是线程安全的。
答案 1 :(得分:11)
在您的情况下,并发读取您的数组将是线程安全的。
至于算法的有效性,根据数组的大小,如果它适合缓存,那么你可能会看到出色的性能提升,因为多核有效地“对抗”CPU中的缓存。如果他们正在努力用相同的信息填充缓存,他们将分享意味着更多的缓存命中和更好的性能。
假设您的阵列适合缓存......
答案 2 :(得分:4)
没有理由不同时读取数组的内容,假设内容永远不会改变。没有并发问题,因此无需复制。
我怀疑你能做些什么来让它更快。
答案 3 :(得分:3)
不应该打扰你。并发读取不是问题。任意数量的线程都可以同时读取相同的内存。
答案 4 :(得分:3)
如果.NET性能和并行性受到威胁,我建议尝试在F#中编写这个特定的算法。 F#编译器将生成.NET code that has 2-6 better performance。
答案 5 :(得分:2)
更新数据时,线程安全只是一个问题。如果您有多个并发线程 正在更新 ,则必须在同步机制中包装更新(并且如果更新不是原子的,则读取更新)。对于只读数据结构,并发性不是问题。
答案 6 :(得分:1)
赋值运算符不是线程安全的。
这意味着如果您的线程只读取数组 - 如果数组在程序启动时初始化并且没有更改 - 那么您就是安全的。
但是,如果存在编写新值的作者,则您很容易受到竞争条件的影响。
基本问题是这个;读者开始读取整数。该值从内存加载到寄存器中。此时,读者交换掉了。然后,编写器更新内存中的值。然后读者重新接通并对他加载的值进行操作 - 这不再正确。
这意味着if()
之类的内容无法可靠地运行。例如,
if( int_array[5] == 10 )
{
}
当int_array[5]
的内存中值不再为10时,可能会触发。
我相信C#,您应该可以访问Interlocked*()
函数调用,例如InterlockedCompareAndSwap()
。在这种情况下,这些将允许您轻松实现线程安全。