6

遇到过这样一种情况,即简单的 .net fibonniacci 代码在一组特定的服务器上速度较慢,唯一明显不同的是 CPU。AMD Opteron 处理器 6276 - 11 秒 Intel Xeon XPU E7 - 4850 - 7 秒

代码适用于 x86 并使用 .NET 框架 4.0。-两者之间的时钟速度相似,实际上 PassMark 基准测试为 AMD 提供了更高的分数。- 已在场中的其他 AMD 服务器上尝试过此操作,但时间较慢。- 甚至我本地的 I7 机器也能更快地运行代码。

斐波那契代码:

class Program
{
    static void Main(string[] args)
    {
        const int ITERATIONS = 10000;
        const int FIBONACCI = 100000;

        var watch = new Stopwatch();
        watch.Start();


        DoFibonnacci(ITERATIONS, FIBONACCI);

        watch.Stop();

        Console.WriteLine("Total fibonacci time: {0}ms", watch.ElapsedMilliseconds);
        Console.ReadLine();
    }

    private static void DoFibonnacci(int ITERATIONS, int FIBONACCI)
    {
        for (int i = 0; i < ITERATIONS; i++)
        {
            Fibonacci(FIBONACCI);
        }
    }

    private static int Fibonacci(int x)
    {
        var previousValue = -1;
        var currentResult = 1;

        for (var i = 0; i <= x; ++i)
        {
            var sum = currentResult + previousValue;
            previousValue = currentResult;
            currentResult = sum;
        }

        return currentResult;
    }

}

关于可能发生的事情的任何想法?

4

1 回答 1

7

正如我们在评论中确定的那样,您可以通过将进程固定到 AMD Opteron 机器上的特定处理器来解决此性能问题。

被这个并非真正主题的问题所激发,我决定看看单核固定会产生如此不同的可能场景(从 11 秒到 7 秒似乎有点极端)。

最合理的答案并不是那么具有革命性:

AMD Opteron 系列采用所谓的 NUMA 架构中的HyperTransport ,而不是您在 Intel 的 SMP CPU(包括 Xeon 4850)上发现的传统 FSB

我的猜测是,这种症状源于 NUMA 架构中的各个节点具有单独的缓存,而不是共享处理器缓存的 Intel CPU。

换句话说,当 Opteron 上的节点之间的连续计算转移时,缓存会被刷新,而像 Xeon 4850 这样的 SMP 架构中的处理器之间的平衡则没有这种影响,因为缓存是共享的。

在 .NET 中设置亲和力非常简单,只需选择一个处理器(为简单起见,我们只选择第一个):

static void Main(string[] args)
{
    Console.WriteLine(Environment.ProcessorCount);
    Console.Read();

    //An AffinityMask of 0x0001 will make sure the process is always pinned to processer 0
    Process thisProcess = Process.GetCurrentProcess();
    thisProcess.ProcessorAffinity = (IntPtr)0x0001; 

    const int ITERATIONS = 10000;
    const int FIBONACCI = 100000;

    var watch = new Stopwatch();
    watch.Start();


    DoFibonnacci(ITERATIONS, FIBONACCI);

    watch.Stop();

    Console.WriteLine("Total fibonacci time: {0}ms", watch.ElapsedMilliseconds);
    Console.ReadLine();
}

虽然我很确定这在 NUMA 环境中不是很聪明。

Windows 2008 R2 有一些很酷的本机 NUMA 功能,我发现了一个有前途的 codeplex 项目,它也有一个 .NET 包装器:http ://multiproc.codeplex.com/

我完全没有资格教你如何使用这项技术,但这应该会为你指明正确的方向。

于 2013-09-24T20:50:02.097 回答