多线程填充数组
Multithreading Fill Array
在 C# Net 2.0 上
代码运行速度比单线程版本稍慢。 xDiff = 2100, yDiff = 2000;单线程中将近 14 秒,多线程中为 16 秒(此代码)。一定是出了什么问题。
我需要填写结果数组。数组节点只写一次数据,没有读,所以应该适合多线程。
double[,] result = new double[xDiff, yDiff];
int threadCount = Environment.ProcessorCount;
ManualResetEvent finished = new ManualResetEvent(false);
int perthread = xDiff / threadCount;
int left = xDiff % threadCount;
int toProcess = threadCount;
int s = 0;
int e = left;
for (int ii = 0; ii < threadCount; ii++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
{
for (int x = s; x < e; x++)
for (int y = 0; y < yDiff; y++)
{
result[x, y] = DoWork((xStart + x), (yStart + y), p)
}
if (System.Threading.Interlocked.Decrement(ref toProcess) == 0) finished.Set();
}), null);
s = e;
e += perthread;
}
finished.WaitOne();
return result;
xStart,yStart 是double,p 是大的class。 DoWork 函数只调用 p 的一些函数而不调用 writes/change class.
上的任何数据
简要结果[x, y] = DoWork((xStart + x), (yStart + y), p);
我需要尽快填充数组。我该怎么做?
我认为这里的问题是变量 s
和 e
是在线程外被修改的闭包,所以线程得到了错误的值并且使用了不正确的范围。
要查看是否是这种情况,请尝试添加一个 Console.WriteLine()
或 Trace.WriteLine()
以在线程内打印出 s
和 e
的值(在打电话给 QueueUserWorkItem()
) 看看这是不是正在发生的事情。
要解决此问题,请将修改后的闭包复制到临时变量中并在线程中使用它们,如下所示:
for (int ii = 0; ii < threadCount; ii++)
{
int ts = s; // Copy them outside the loop.
int te = e;
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
{
for (int x = ts; x < te; x++) // Use the copy here.
另见 Access to Modified Closure
在 C# Net 2.0 上
代码运行速度比单线程版本稍慢。 xDiff = 2100, yDiff = 2000;单线程中将近 14 秒,多线程中为 16 秒(此代码)。一定是出了什么问题。 我需要填写结果数组。数组节点只写一次数据,没有读,所以应该适合多线程。
double[,] result = new double[xDiff, yDiff];
int threadCount = Environment.ProcessorCount;
ManualResetEvent finished = new ManualResetEvent(false);
int perthread = xDiff / threadCount;
int left = xDiff % threadCount;
int toProcess = threadCount;
int s = 0;
int e = left;
for (int ii = 0; ii < threadCount; ii++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
{
for (int x = s; x < e; x++)
for (int y = 0; y < yDiff; y++)
{
result[x, y] = DoWork((xStart + x), (yStart + y), p)
}
if (System.Threading.Interlocked.Decrement(ref toProcess) == 0) finished.Set();
}), null);
s = e;
e += perthread;
}
finished.WaitOne();
return result;
xStart,yStart 是double,p 是大的class。 DoWork 函数只调用 p 的一些函数而不调用 writes/change class.
上的任何数据简要结果[x, y] = DoWork((xStart + x), (yStart + y), p); 我需要尽快填充数组。我该怎么做?
我认为这里的问题是变量 s
和 e
是在线程外被修改的闭包,所以线程得到了错误的值并且使用了不正确的范围。
要查看是否是这种情况,请尝试添加一个 Console.WriteLine()
或 Trace.WriteLine()
以在线程内打印出 s
和 e
的值(在打电话给 QueueUserWorkItem()
) 看看这是不是正在发生的事情。
要解决此问题,请将修改后的闭包复制到临时变量中并在线程中使用它们,如下所示:
for (int ii = 0; ii < threadCount; ii++)
{
int ts = s; // Copy them outside the loop.
int te = e;
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
{
for (int x = ts; x < te; x++) // Use the copy here.
另见 Access to Modified Closure