我正在遵循第107页上的“并行编程模式:通过.NET Framework 4(https://www.microsoft.com/en-us/download/details.aspx?id=19222)了解和应用并行模式”中的示例。声明使用ThreadLocal的Value成员的本地副本比使用Threadlocal.Value本身要快。我对此进行了测试,确实是这样。但是为什么呢?
从代码中可以看到,_vector2.Value的本地副本保存在vector2中,并且此本地副本用于对所有项求和。如果您使用
_vector2.Value[i] += _vector1.Value[i]
代替
vector2[i] += vector1[i]
代码运行得一样好,尽管速度较慢。这就是本文所述的内容。现在,int []是引用类型。这意味着当您在vector2中进行复制时,您实际上是在ThreadLocal的Value成员中复制原始int []的引用。注释掉_vector2.Value = vector2
可以证实这一点。打印结果保持不变。因此,我认为不需要此任务。
现在,由于_vector2.Value和vector2引用了相同的数据,使用本地副本(vector2)的工作速度又如何更快?在我的测试中,速度大约提高了4倍。有谁知道我想念的东西吗?
class ReferenceList
{
const int VECTOR_LENGTH = 100000000;
private ThreadLocal<int[]> _vector1 = new ThreadLocal<int[]>(() => Enumerable.Range(1, VECTOR_LENGTH).ToArray());
private ThreadLocal<int[]> _vector2 = new ThreadLocal<int[]>(() => Enumerable.Range(1, VECTOR_LENGTH).ToArray());
internal void DoWork()
{
int[] vector1 = _vector1.Value;
int[] vector2 = _vector2.Value;
for (int i = 0; i < VECTOR_LENGTH; i++)
{
// This is the fast way (as in the document)
vector2[i] += vector1[i];
// This is the slow way
//_vector2.Value[i] += _vector1.Value[i];
}
// Since int[] is a reference type. This step is not needed, I think. The result is not influenced when commenting out this line
_vector2.Value = vector2;
Console.WriteLine($"Thread-{Thread.CurrentThread.ManagedThreadId} Result: {String.Join(", ", _vector2.Value.Take(10))}");
}
答案 0 :(得分:1)
vector1
是对该数组的直接引用。 没有什么比这更快的了。
_vector1
是不是直接引用数组的引用。 _vector1.Value
将结果具有相同的值-但根据the source code,要获得该值需要花费一些精力。因此,每次您要求.Value
时,您都会再次遭受性能(执行方法等方面)的打击(即使您知道它会返回相同的值,也需要花费一些精力才能工作)出来)。 而这忽略了其他相关成本,例如可能减少的数据局部性,增加的高速缓存未命中率等。