虽然计算机有32个内核,但多线程应用程序使用16个线程可以达到最佳效果

本文关键字:线程 16个 最佳 32个 计算机 内核 应用程序 多线程 | 更新日期: 2023-09-27 18:24:55

我有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();

虽然计算机有32个内核,但多线程应用程序使用16个线程可以达到最佳效果

首先,我认为您肯定应该用新的.NET 4.0 Parallel.For构造来替换您的构造:

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

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

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

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

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

来自64位应用程序:

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