C# 尽管计算机有32个内核,但多线程应用程序使用16个线程来实现最佳性能

C# 尽管计算机有32个内核,但多线程应用程序使用16个线程来实现最佳性能,c#,multithreading,C#,Multithreading,我有AMD Opteron(tm)6282SE 2.6 GHZ 32核(2个处理器,每个16核) 我有C#数学应用程序,可以在并行核上运行 我的应用程序的主要部分获得的最佳性能是当我使用16个线程(即将工作划分为16个线程)时,该部分的最佳运行时间为1MS 如果我使用超过16个线程,我会得到超过1MS的时间 我的问题是,假设我有32个内核,为什么我不能将这个部分与更多线程并行 这是并行运行的代码 int N = 238; int P = 16; int Chunk = N / P; AutoR

我有AMD Opteron(tm)6282SE 2.6 GHZ 32核(2个处理器,每个16核) 我有C#数学应用程序,可以在并行核上运行

我的应用程序的主要部分获得的最佳性能是当我使用16个线程(即将工作划分为16个线程)时,该部分的最佳运行时间为1MS

如果我使用超过16个线程,我会得到超过1MS的时间

我的问题是,假设我有32个内核,为什么我不能将这个部分与更多线程并行

这是并行运行的代码

int N = 238;
int P = 16;

int Chunk = N / P;
AutoResetEvent signal = new AutoResetEvent(false);
// use a counter to reduce
int counter = P;

// kernel transitions   
for (int c = 0; c < P; c++)
{           
    // for each chunk
    ThreadPool.QueueUserWorkItem(delegate(Object o)
    {
        int lc = (int)o;
        for (int i = lc * Chunk; i < (lc + 1 == P ? N : (lc + 1) * Chunk); i++)
        {
           // do something
        }
        if (Interlocked.Decrement(ref counter) == 0)
        {
            signal.Set();
        }
    }, c);
}
signal.WaitOne();
int N=238;
int P=16;
int Chunk=N/P;
自动恢复事件信号=新自动恢复事件(假);
//使用计数器来减少
int计数器=P;
//内核转换
for(int c=0;c
首先,我认为您应该用新的.NET 4.0
并行版本替换您的结构。对于
结构:

Parallel.For(0, N,
    i => 
    {
       // do something
    });

其次,实际上您使用的是两个CPU,每个CPU有16个内核。最有可能的是,调度程序足够聪明,可以利用本地性,将所有16个线程调度到同一个CPU上。当另一个CPU开始工作时,根据您的计算,访问共享数据需要一直通过主存,以确保两个CPU之间的一致性。这可能会非常昂贵。

ThreadPool
是被动的,需要一段时间才能将新线程添加到池中。基本上,如果一段时间内没有足够的线程,它会增加线程池的大小,当有更多空闲时,它会将其恢复。因此它在对象设置的minmax大小之间波动-可返回或设置


如果您知道需要多少线程,请使用确保开始时有足够的线程。

问题是因为我的EXE文件已编译为32位,而操作系统为64位

发件人:

由于x86仿真和WOW64子系统的设计 安腾处理器系列,应用程序仅限于在 一个处理器


阿姆达尔定律是最基本的:我会尝试用
系统、线程、任务、并行.For
实现同样的事情,并比较结果好问题,我没有答案,但你能用Monitor代替AutoResetEvent吗?AutoResteEvent是一个内核模式同步对象,它比监视器等托管同步对象慢得多。我在这里完全猜到了,但也许使用AutoResteEvent会带来一些使用Monitor可以避免的事情?@HansPassant:这很有趣,但它没有说明如果在更多内核上运行会变得更慢的原因,它只是说明了最大速度增加可能是什么。这一点,N非常小。我们不知道它在索引什么,但是,除非它是一个包含冗长方法的大型复杂对象数组,否则它可能太小,无法实现有效的并发。@Tudor:为什么不在发布之前写出完整的答案呢?我不介意给出一个简短的答案,然后扩展它,但当你发布一些不是答案的东西,然后将答案编辑到其中时,确实感觉有点像“首先”发帖……实际上,使用
并行。因为
可能会解决他的问题,因此,在我看来,单独测试这一变化绝对是值得的。我尝试了上述所有建议,但都无济于事。我尝试使用Parallel.For(0,N,I=>{//do something});它给了我大约1MS的相同结果,我尝试使用Monitor而不是AutoResteEvent,并尝试在线程池中设置最小线程。非常奇怪的是,考虑到我有两个处理器,每个处理器16个,最佳的线程数正好是16个。@user1211587:你能在
//做点什么
中公布你在做什么吗?正如我在回答中提到的,两个处理器之间的数据交换可能是导致速度减慢的原因。@user1211587“do something”块是一个简单的数学应用程序。它包含许多数学计算(简单的操作,如log,^等)它还包含简单的c代码(许多if,排序时等)。我尝试设置线程池的最小线程,但没有帮助。默认最小大小为32。我试图增加它,但如前所述,它没有帮助。