2014-04-26 2 views
0

아마 내가 잘못하고있는 것이지만, 그 SIMD가 scallar 버전보다 느리다.SIMD가 무차별적인 힘보다 느린 이유

배열의 값을 증가시키고 싶습니다. Microsoft SIMD (NuGet 패키지 Microsoft.Bcl.Simd 시험판)를 사용하고 있습니다. 그것은 베타 버전이지만 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 . . . 
+0

, 당신은'simd' 태그의 설명을 보라; 특히 "더 긴 스트림"과 "순진하게 최적화 된 SIMD 코드는 더 느립니다". SIMD (및 병렬화)를 사용하면 오버 헤드가 발생합니다. 충분히 큰 데이터 크기로 사용하지 않으면 보상을받지 못할 수도 있습니다. – SJuan76

+0

왜'var increment = new Vector (inc);'이 루프 안에 있습니까? –

+2

'VectorMath.IsHardwareAccelerated'가 true를 반환합니까? (RyuJIT를 제대로 설정했는지 궁금합니다.) – BrainSlugs83

답변

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

나 패키지에서 인용 보자 :이 패키지

유형은 이 아닌 SIMD 활성화 JIT 컴파일러와 하드웨어에 사용하도록 허용하는 IL에서 구현됩니다. 그러나 SIMD 명령어를 실제로 사용하려면 명령에서 SIMD 명령어를 내보내려면 이러한 유형을 알고있는 JIT 컴파일러에서 실행해야합니다. 현재 .NET 4.5.1 런타임은 그렇지 않습니다. .NET 코드 생성 팀은 코드 명 "RyuJIT"라는 새로운 JIT의 CTP를 게시했습니다. CTP는 x64 용으로 컴파일 할 때 SIMD 지원을 추가합니다.

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; 
} 
관련 문제