为什么SIMD比蛮力慢

时间:2014-04-26 16:43:34

标签: c# .net performance sse simd

也许我做错了什么,但我觉得SIMD比scallar版本慢。

我只想增加数组的值。我正在使用Microsoft SIMD(NuGet包Microsoft.Bcl.Simd Prerelease)。它是测试版,但它应该可以正常使用int和float,但它没有。

我的板凳

using System;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;

namespace ConsoleApplication58
{
    class Program
    {
        static void Main()
        {
            var r = new Random();
            var sw = Stopwatch.StartNew();
            int[] values = Enumerable.Range(0, 1000000).ToArray();
            sw.Stop();
            Console.WriteLine("TEST GENERATED IN {0}", sw.Elapsed);
            int trash = 0;
            Stopwatch sw1 = new Stopwatch(), sw2 = new Stopwatch();
            for (int i = 0; i < 100; i++)
            {
                sw1.Start();
                var result = SimdIncrement(values, 10);
                sw1.Stop();
                sw2.Start();
                var result2 = SimpleIncrement(values, 10);
                sw2.Stop();

                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();

                unchecked
                {
                    trash ^= result[r.Next(values.Length)];
                    trash ^= result2[r.Next(values.Length)];
                }
            }
            Console.WriteLine("SIMD = {0}", sw1.Elapsed);
            Console.WriteLine("Brute = {0}", sw2.Elapsed);

            Console.WriteLine("Trash value = {0}", trash);
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static int[] SimpleIncrement(int[] values,int inc)
        {
            int[] result = new int[values.Length];
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = values[i] + inc;
            }
            return result;
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static int[] SimdIncrement(int[] values,int inc)
        {
            int[] result = new int[values.Length];
            for (int i = 0; i < values.Length; i += 4)
            {
                var vector = new Vector<int>(values, i);
                var increment = new Vector<int>(inc);
                vector += increment;
                vector.CopyTo(result, i);
            }
            return result;
        }
    }
}

结果:

TEST GENERATED IN 00:00:00.0171804
SIMD = 00:00:02.1456817
Brute = 00:00:00.1576084
Trash value = 548547
Press any key . . .

2 个答案:

答案 0 :(得分:3)

我讨厌更加狡猾,但这里的SIMD在哪里? Microsoft SIMD程序包不会执行SIMD指令....这是正常的字节码。要使它使用SIMD,您必须安装RyuJit并告诉它。

这是兼容模式 - MS SIMD类包含正常操作的字节码。新运行时将知道如何处理它们而不触及字节代码,但您必须立即安装它(预发布)。

http://blogs.msdn.com/b/dotnet/archive/2013/09/30/ryujit-the-next-generation-jit-compiler.aspx

让我引用一揽子方案:

  

此包中的类型在IL中实现,允许它们   用于非SIMD启用的JIT编译器和硬件。但是,在   为了实际使用SIMD指令,您需要在JIT上运行   知道这些类型的编译器,以便发出SIMD   说明。当前的.NET 4.5.1运行时没有。 .NET代码   代际团队发布了新JIT的CTP,代号为   &#34; RyuJIT&#34 ;. CTP在编译x64时添加了SIMD支持。

答案 1 :(得分:1)

您的SIMD版本应更改为基于矢量的实际添加方法:

[MethodImpl(MethodImplOptions.NoInlining)]
private static int[] simdIncrement(int[] values, int inc)
{    
    var vector = new Vector<int>(values);
    var vectorAddResults = vector + new Vector<int>(inc);

    var result = new int[values.Length];
    vectorAddResults.CopyTo(result);
    return result;
}