【问题标题】:Multithreading Fill Array多线程填充数组
【发布时间】:2015-03-02 10:02:59
【问题描述】:

在 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 是一个大类。 DoWork 函数只调用 p 的一些函数,但不写入/更改类上的任何数据。

简单结果[x, y] = DoWork((xStart + x), (yStart + y), p); 我需要尽可能快地填充数组。我该怎么做?

【问题讨论】:

  • DoWork 是否在做一些阻塞操作?如果是这样,您最好在每次调用 DoWork 时排队一个新的工作项。请注意,QueueUserWorkItem 实际上并没有创建新线程
  • 考虑在 Parallel 类中使用现成的循环之一。你的情况看起来并不特别。
  • @usr 起初我忽略了这一点,但 OP 使用 .NET 2.0。

标签: c# arrays multithreading .net-2.0


【解决方案1】:

我认为这里的问题是变量se 是在线程之外被修改的闭包,因此线程得到了错误的值并且使用了不正确的范围。

要查看是否是这种情况,请尝试添加Console.WriteLine()Trace.WriteLine() 以在线程内(在调用QueueUserWorkItem() 之后)打印出se 的值,看看是否这样是怎么回事。

要解决这个问题,请将修改后的闭包复制到临时变量中并在线程中使用它们,如下所示:

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

【讨论】:

  • 谢谢我错过了。当我检查 s 和 e 时,所有线程都试图填充所有数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-26
  • 2011-07-11
  • 1970-01-01
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
相关资源
最近更新 更多