2

我需要根据用户 PC 的逻辑核心数在不同的进程上分配工作负载。工作量由以下代码完成:

static void work()
{
    WorkData myData = new WorkData();
    Worker myWorker = new Worker(myData);
    MyWorker.doWork()
}

我用这段代码计算逻辑核心:

int nbProcessors = 1;
foreach (var item in new System.Management.ManagementObjectSearcher("Select *  from Win32_ComputerSystem").Get())
{
    nbProcessors = Convert.ToInt32(item["NumberOfLogicalProcessors"]);
}

现在,我必须通过在逻辑核心上共享工作来完成我的 work() 10000 次,所以对于我的电脑来说,这意味着启动 8 个进程,每个进程有 1250 次 work() 迭代。我还需要每个进程都有自己的数据,这样我就不会发生冲突。

我怎样才能做到这一点?

4

5 回答 5

2

我认为您应该查看Parallel方法和ThreadPool方法。
这两个类都依赖于当前的工作站配置,因此您可以轻松地将它们用于您的任务。

并行使用示例:

并行循环

int n = 10 000;
Parallel.For(0, n, (i, loopState) =>
{
  // ... 
  if (/* stopping condition is true */)
  {
    loopState.Break();
    return;   
  }
});

线程池面向任务的例子

public void DoWork()
{
    // Queue a task.
    System.Threading.ThreadPool.QueueUserWorkItem(
        new System.Threading.WaitCallback(SomeLongTask));
    // Queue another task.
    System.Threading.ThreadPool.QueueUserWorkItem(
        new System.Threading.WaitCallback(AnotherLongTask));
}

private void SomeLongTask(Object state)
{
    // Insert code to perform a long task.
}

private void AnotherLongTask(Object state)
{
    // Insert code to perform a long task.
}

评论更新:

任务并行库(Parralel 类)在内部使用 Threading.Tasks 命名空间,并管理一些进程:

ThreadPool 上的线程调度

另外两个关于:Task ParallelismData Parallelism的链接。我认为第二个链接可以帮助您平衡数据的工作。

如果可能,如果工作负载变得不平衡,调度程序会在多个线程和处理器之间重新分配工作。

于 2012-11-16T10:01:39.120 回答
2

从 C# 4.0 开始,您可以使用Task Parallel Library,它会自动进行负载平衡:

Parallel.For(0, 10000, p => work());

或者

ParallelEnumerable.Range(0, 10000).ForAll(p => work());

请参阅:.NET Framework 中的并行编程

于 2012-11-16T10:04:08.017 回答
1

看看TPL

   Parallel.For (0,10000, item => {
       WorkData myData = new WorkData();
       Worker myWorker = new Worker(myData);
       MyWorker.doWork()
   });

它将在核心之间自动拆分。但如果需要,您可以手动设置线程数

于 2012-11-16T10:00:50.843 回答
1

嗯,你知道你可以通过访问属性来获得逻辑处理器数量:

Environment.ProcessorCount

在我的四核 HT 机器上返回 8 - 有点结账。

如果您有固定数量的迭代(而不是对列表或其他内容进行迭代),那么您可以使用:

var parallelOptions = new ParallelOptions
{
    MaxDegreeOfParallelistm = Environment.ProcessorCount
};


//edited per comment
Parallel.For(0, 10000, parallelOptions, () =>
{
    WorkData myData = new WorkData();
    Worker myWorker = new Worker(myData);
    MyWorker.doWork() 
});

如果您必须对列表进行一些分区,那么 partitioner 就会发挥作用:

var partitioner = Partitioner.Create(yourList);
var parallelOptions = new ParallelOptions
{
    MaxDegreeOfParallelism = Environment.ProcessorCount
};

Parallel.ForEach(partitioner, parallelOptions, (listItem, loopState) =>
{
   //Do something
}

尽管请注意,AFAIKParallel默认情况下循环会产生与内核一样多的线程。

于 2012-11-16T10:03:35.627 回答
0

看看这个线程指南。
以一种非常容易理解的方式从非常基本的线程到并行编程。
简而言之,它是 c# 4.0 一书中的 5 章。
就个人而言,它帮助我更好地理解线程。

于 2012-11-16T10:43:40.323 回答