.NET / C # рдореЗрдВ SIMD рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЕрд╡рд▓реЛрдХрди

рдпрд╣рд╛рдБ .NET Framework рдФрд░ .NET рдХреЛрд░ рдореЗрдВ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╡реЗрдХреНрдЯрд░рд╛рдЗрдЬреЗрд╢рди рдХреНрд╖рдорддрд╛рдУрдВ рдкрд░ рдПрдХ рддреНрд╡рд░рд┐рдд рдирдЬрд╝рд░ рд╣реИред рдпрд╣ рд▓реЗрдЦ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬреЛ рдЗрди рддрдХрдиреАрдХреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВред рдореИрдВ рдпрд╣ рднреА рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ .NET рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореВрд▓ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП "рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдХрд▓рд┐рдд" рднрд╛рд╖рд╛рдУрдВ рд╕реЗ рдкреАрдЫреЗ рдирд╣реАрдВ рд╣реИред


рдореИрдВ рдЕрднреА рд╡реИрд╢реНрд╡реАрдХрд░рдг рддрдХрдиреАрдХ рд╕реАрдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЗрд╕рд▓рд┐рдП, рдореИрдВ рд╕рд░рд╛рд╣рдирд╛ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рд╕рдореБрджрд╛рдп рдХреЗ рд╕рджрд╕реНрдп рд╕реНрдкрд╖реНрдЯ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдкрд╛рддреЗ рд╣реИрдВ рдпрд╛ рд╡рд░реНрдгрд┐рдд рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВред


рдХреБрдЫ рдЗрддрд┐рд╣рд╛рд╕


2015 рдореЗрдВ .NET рдлреНрд░реЗрдорд╡рд░реНрдХ 4.6 рдореЗрдВ SIMD рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ Matrix3x2, Matrix4x4, Plane, Quaternion, Vector2, Vector3 рдФрд░ Vector4 рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝реЗ рдЧрдПред рдЙрдиреНрд╣реЛрдВрдиреЗ рд╕рджрд┐рд╢ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рди рдХреА рдЕрдиреБрдорддрд┐ рджреАред рдЕрдЧрд▓рд╛ рд╡реЗрдХреНрдЯрд░ <T> рдкреНрд░рдХрд╛рд░ рдерд╛ рдЬрд┐рд╕рдиреЗ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рд╡реЗрдХреНрдЯрд░ рдХрд░рдиреЗ рдХреЗ рдЕрдзрд┐рдХ рдЕрд╡рд╕рд░ рджрд┐рдПред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдХрдИ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЕрднреА рднреА рдЕрд╕рдВрддреБрд╖реНрдЯ рдереЗ рдХреНрдпреЛрдВрдХрд┐ рдЗрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХреЛрдбрд░реНрд╕ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдзрд╛рд░рд╛рдПрдБ рдереАрдВ рдФрд░ рдЖрдзреБрдирд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЗрдВ SIMD рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреА рдкреВрд░реА рдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рдереЗред рдЕрдм .NET рдХреЛрд░ 3.0 рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ System.Runtime.Intrinsics рдирд╛рдо рд╕реНрдерд╛рди рд╣реИ рдЬреЛ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЪреБрдирд╛рд╡ рдореЗрдВ рдмрд╣реБрдд рд╕реНрд╡рддрдВрддреНрд░рддрд╛ рджреЗрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЧрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ RyuJit рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдпрд╛ рддреЛ x64 рдЕрд╕реЗрдВрдмрд▓реА рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗрдВ рдпрд╛ 32-рдмрд┐рдЯ рдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреЗрдВ рдФрд░ AnyCPU рдЕрд╕реЗрдВрдмрд▓реА рдХрд╛ рдЪрдпрди рдХрд░реЗрдВред рдореИрдВрдиреЗ Intel Core i7-6700 3.40 GHz (Skylake) CPU рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рд╕рднреА рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЪрд▓рд╛рдПред


рд╕рд╛рд░ рддрддреНрд╡реЛрдВ рдХреЛ рд╕рдореЗрдЯрдирд╛


рдореИрдВрдиреЗ рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рдХрд╛рд░реНрдп рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдЬреЛ рдЖрдо рддреМрд░ рдкрд░ рдкрд╣рд▓реЗ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рд╡реИрд╢реНрд╡реАрдХрд░рдг рд╢рд╛рдорд┐рд▓ рд╣реЛред рдпрд╣ рд╕рд░рдгреА рддрддреНрд╡реЛрдВ рдХрд╛ рдпреЛрдЧ рдЦреЛрдЬрдиреЗ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдПрд░реЗ рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рдЪрд╛рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦрддреЗ рд╣реИрдВред


рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:


public int Naive() { int result = 0; foreach (int i in Array) { result += i; } return result; } 

LINQ- рдЖрдзрд╛рд░рд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:


 public long LINQ() => Array.Aggregate<int, long>(0, (current, i) => current + i); 

System.Numerics рд╕реЗ рд╡реИрдХреНрдЯрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:


 public int Vectors() { int vectorSize = Vector<int>.Count; var accVector = Vector<int>.Zero; int i; var array = Array; for (i = 0; i <= array.Length - vectorSize; i += vectorSize) { var v = new Vector<int>(array, i); accVector = Vector.Add(accVector, v); } int result = Vector.Dot(accVector, Vector<int>.One); for (; i < array.Length; i++) { result += array[i]; } return result; } 

System.Runtime.Intrinsics рдирд╛рдорд╕реНрдерд╛рди рд╕реЗ рдХреЛрдб рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:


 public unsafe int Intrinsics() { int vectorSize = 256 / 8 / 4; var accVector = Vector256<int>.Zero; int i; var array = Array; fixed (int* ptr = array) { for (i = 0; i <= array.Length - vectorSize; i += vectorSize) { var v = Avx2.LoadVector256(ptr + i); accVector = Avx2.Add(accVector, v); } } int result = 0; var temp = stackalloc int[vectorSize]; Avx2.Store(temp, accVector); for (int j = 0; j < vectorSize; j++) { result += temp[j]; } for (; i < array.Length; i++) { result += array[i]; } return result; } 

рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдЙрди 4 рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХрд┐рдпрд╛ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП:


рд╡рд┐рдзрд┐ItemsCountрдореАрдирддреНрд░реБрдЯрд┐StdDevрдЕрдиреБрдкрд╛рдд
рдЕрдиреБрднрд╡рд╣реАрди103.531 рдПрди.рдПрд╕.0.0336 рдПрди.рдПрд╕.0.0314 рдПрди.рдПрд╕.1.00
LINQ1076.925 рдПрди.рдПрд╕.0.4166 рдПрди.рдПрд╕.0.3897 рдПрди.рдПрд╕.21.79
рд╡реИрдХреНрдЯрд░102.750 рдПрди.рдПрд╕.0.0210 рдПрди.рдПрд╕.0.0196 рдПрди.рдПрд╕.0.78
intrinsics106.513 рдПрди.рдПрд╕.0.0623 рдПрди.рдПрд╕.0.0582 рдПрди.рдПрд╕.1.84
рдЕрдиреБрднрд╡рд╣реАрди10047.982 рдПрди.рдПрд╕.0.3975 рдПрди.рдПрд╕.0.3524 рдПрди.рдПрд╕.1.00
LINQ100590.414 рдПрди.рдПрд╕.3.8808 рдПрди.рдПрд╕.рей.рекрекрежреи рдПрди.рдПрд╕.12.31
рд╡реИрдХреНрдЯрд░10010.122 рдПрди.рдПрд╕.0.0747 рдПрди.рдПрд╕.0.0699 рдПрди.рдПрд╕.0.21
intrinsics10014.277 рдПрди.рдПрд╕.0.0566 рдПрди.рдПрд╕.0.0529 рдПрди.рдПрд╕.0.30
рдЕрдиреБрднрд╡рд╣реАрди1000569.910 рдПрди.рдПрд╕.реи. .реи реп s рдПрди.рдПрд╕.2.6469 рдПрди.рдПрд╕.1.00
LINQ10005,658.570 рд░реБрдкрдпреЗ31.7465 рдПрди.рдПрд╕.29.6957 рдПрди.рдПрд╕.9.93
рд╡реИрдХреНрдЯрд░100079.598 рдПрди.рдПрд╕.0.3498 рдПрди.рдПрд╕.0.3272 рдПрди.рдПрд╕.0.14
intrinsics100066.970 рдПрдирдПрд╕0.3937 рдПрди.рдПрд╕.0.3682 рдПрди.рдПрд╕.0.12
рдЕрдиреБрднрд╡рд╣реАрди100005,637.571 рдПрди.рдПрд╕.37.5050 рдПрди.рдПрд╕.29.2814 рдПрди.рдПрд╕.1.00
LINQ1000056,498.987 рдПрди.рдПрд╕.294.8776 рдПрди.рдПрд╕.275.8287 рдПрди.рдПрд╕.10.02
рд╡реИрдХреНрдЯрд░10000772.900 рдПрди.рдПрд╕.2.6802 рдПрди.рдПрд╕.2.5070 рдПрди.рдПрд╕.0.14
intrinsics10000579.152 рдПрди.рдПрд╕.2.8371 рдПрди.рдПрд╕.реи.ремрелрейs рдПрди.рдПрд╕.0.10
рдЕрдиреБрднрд╡рд╣реАрди10000056,352.865 рдПрди.рдПрд╕.230.7916 рдПрди.рдПрд╕.215.8826 рдПрди.рдПрд╕.1.00
LINQ100000562,610.571 рдПрди.рдПрд╕.3,775.7631 рдПрди.рдПрд╕.3,152.9332 рдПрдирдПрд╕9.98
рд╡реИрдХреНрдЯрд░1000008,389.647 рдПрди.рдПрд╕.165.9590 рд░реБрдкрдпреЗ227.1666 рдПрди.рдПрд╕.0.15
intrinsics1000007,261.334 рдПрди.рдПрд╕.89.6468 рдПрди.рдПрд╕.69.9903 рдПрди.рдПрд╕.0.13

рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рдФрд░ LINQ- рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╡реИрдХреНрдЯрд░ рдФрд░ рдЖрдВрддрд░рд┐рдХрддрд╛ рд╡рд╛рд▓реЗ рд╕рдорд╛рдзрд╛рди рдмрд╣реБрдд рддреЗрдЬ рд╣реИрдВред рдЕрдм рд╣рдореЗрдВ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рдЗрди рджреЛ рддрд░реАрдХреЛрдВ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред


рдЖрдЗрдП рд╡реИрдХреНрдЯрд░ рдкрджреНрдзрддрд┐ рдкрд░ рдЕрдзрд┐рдХ рдмрд╛рд░реАрдХреА рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


рд╡реИрдХреНрдЯрд░
 public int Vectors() { int vectorSize = Vector<int>.Count; var accVector = Vector<int>.Zero; int i; var array = Array; for (i = 0; i <= array.Length - vectorSize; i += vectorSize) { var v = new Vector<int>(array, i); accVector = Vector.Add(accVector, v); } int result = Vector.Dot(accVector, Vector<int>.One); for (; i < array.Length; i++) { result += array[i]; } return result; } 

  • int VectorSize = рд╡реЗрдХреНрдЯрд░ <int> .Count; - 4-рдмрд╛рдЗрдЯ рд╕рдВрдЦреНрдпрд╛ рдХреА рдорд╛рддреНрд░рд╛ рд╣рдо рдПрдХ рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рддреНрд╡рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдорд╛рди рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдПрдХ SIMD рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдХрд┐рддрдиреЗ 4-рдмрд╛рдЗрдЯ рдирдВрдмрд░ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд┐рддрдиреЗ рддрддреНрд╡реЛрдВ рдХреЛ рд╕рдорд╡рд░реНрддреА рд░реВрдк рд╕реЗ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ;
  • accVector рдПрдХ рд╡реЗрдХреНрдЯрд░ рд╣реИ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЬрдорд╛ рдХрд░рддрд╛ рд╣реИ;
  • var v = рдирдпрд╛ рд╡реЗрдХреНрдЯрд░ <int> (рд╕рд░рдгреА, i); - рд╕рд░рдгреА рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рдПрдХ рдирдП v рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ i рдЗрдВрдбреЗрдХреНрд╕ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред рдбреЗрдЯрд╛ рдХрд╛ рд╡реЗрдХреНрдЯрд░рд╕рд╛рдЗрдЬрд╝ рдмрд┐рд▓реНрдХреБрд▓ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛;
  • accVector = Vector.Add (accVector, v); - рджреЛ рд╡реИрдХреНрдЯрд░ рд╕рдореНтАНрдорд┐рд▓рд┐рдд рд╣реИрдВред
    рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдРрд░реЗ рдореЗрдВ 8 рд╕рдВрдЦреНрдпрд╛рдПрдБ рд╣реИрдВ: {0, 1, 2, 3, 4, 5, 6, 7} рдФрд░ рд╡реЗрдХреНрдЯрд░рд╕реЗрдЬ == 4ред
    рдлрд┐рд░ рдкрд╣рд▓реЗ рдЪрдХреНрд░ рдХреЗ рджреМрд░рд╛рди рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЙрдЪреНрдЪрд╛рд░рдг = {0, 0, 0, 0}, v = {0, 1, 2, 3} рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рдж accVector рдзрд╛рд░рдг рдХрд░реЗрдЧрд╛: {0, 0, 0, 0} + {0, 1 , 2, 3} = {0, 1, 2, 3}ред
    рджреВрд╕рд░реЗ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рджреМрд░рд╛рди v = {4, 5, 6, 7} рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рдж accVector = {0, 1, 2, 3} + {4, 5, 6, 7} = {4, 6, 8, 10}ред
  • рдЕрдм рд╣рдореЗрдВ рдмрд╕ рд╕рднреА рд╡реЗрдХреНрдЯрд░ рддрддреНрд╡реЛрдВ рдХрд╛ рдпреЛрдЧ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рд╕реНрдХреЗрд▓рд░ рдЧреБрдгрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХрд┐ рдПрдХ рд╕рджрд┐рд╢ рд╕реЗ рднрд░рд╛ рд╣реБрдЖ рд╣реИ: int result = Vector.Dot (accVector, рд╡реЗрдХреНрдЯрд░ <int> .One);
    рдлрд┐рд░ рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ: {4, 6, 8, 10} * {1, 1, 1, 1} = 4 * 1 + 6 * 1 + 8 * 1 + 10 * 1 = 28ред
  • рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдЕрдВрддрд┐рдо рд╡реЗрдХреНрдЯрд░ рдХреЛ рдлрд┐рдЯ рдирд╣реАрдВ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЙрди рдирдВрдмрд░реЛрдВ рдХреЛ рдЕрдВрдд рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЖрдЗрдП рдЖрдВрддрд░рд┐рдХ рдЖрдВрддрд░рд┐рдХ рдХреЛрдб рдореЗрдВ рджреЗрдЦреЗрдВ:


intrinsics
 public unsafe int Intrinsics() { int vectorSize = 256 / 8 / 4; var accVector = Vector256<int>.Zero; int i; var array = Array; fixed (int* ptr = array) { for (i = 0; i <= array.Length - vectorSize; i += vectorSize) { var v = Avx2.LoadVector256(ptr + i); accVector = Avx2.Add(accVector, v); } } int result = 0; var temp = stackalloc int[vectorSize]; Avx2.Store(temp, accVector); for (int j = 0; j < vectorSize; j++) { result += temp[j]; } for (; i < array.Length; i++) { result += array[i]; } return result; } 

рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рд╡реИрдХреНрдЯрд░ рдХреА рддрд░рд╣ рд╣реИ:


  • рд╡реЗрдХреНрдЯрд░рд╕рд╛рдЗрдЬрд╝ рдПрдХ рд╕реНрдерд┐рд░рд╛рдВрдХ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд┐рдзрд┐ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ Avx2 рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ рдЬреЛ 256-рдмрд┐рдЯ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреА рд╣реИред рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдПрдХ рдЬрд╛рдВрдЪ рд╢рд╛рдорд┐рд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдХреНрдпрд╛ рд╡рд░реНрддрдорд╛рди рдкреНрд░реЛрд╕реЗрд╕рд░ Avx2 рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рджреВрд╕рд░рд╛ рдХреЛрдб рдХрд╣рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
     if (Avx2.IsSupported) { DoThingsForAvx2(); } else if (Avx.IsSupported) { DoThingsForAvx(); } ... else if (Sse2.IsSupported) { DoThingsForSse2(); } ... 
  • var accVector = рд╡реЗрдХреНрдЯрд░256 <int> .Zero; accVector рдХреЛ рд╢реВрдиреНрдп-рдмрд┐рдЯ рд╡реЗрдХреНрдЯрд░ рд╕реЗ рднрд░рд╛ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
  • рдирд┐рд╢реНрдЪрд┐рдд (int * ptr = Array) - рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХ рдХреЛ ptr рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред
  • рдЕрдЧрд▓рд╛ рд╡реИрдХреНрдЯрд░ рдХреЗ рд╕рдорд╛рди рдСрдкрд░реЗрд╢рди рд╣реИрдВ: рдПрдХ рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░рдирд╛ рдФрд░ рджреЛ рд╡реИрдХреНрдЯрд░ рдЬреЛрдбрд╝рдирд╛ред
  • рд╡реЗрдХреНрдЯрд░ рддрддреНрд╡реЛрдВ рдХрд╛ рдпреЛрдЧ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:
    • рд╕реНрдЯреИрдХ рдкрд░ рдПрдХ рд╕рд░рдгреА рдмрдирд╛рдПрдБ: var temp = stackalloc int [VectorSize];
    • рдЗрд╕ рд╕рд░рдгреА рдореЗрдВ рдПрдХ рд╡реЗрдХреНрдЯрд░ рд▓реЛрдб рдХрд░реЗрдВ: Avx2.Store (рдЕрд╕реНрдерд╛рдпреА, accVector);
    • рдЪрдХреНрд░ рдХреЗ рджреМрд░рд╛рди рдпреЛрдЧ рдХреЗ рддрддреНрд╡ред
  • рдЕрдЧрд▓рд╛, рд╡реЗ рддрддреНрд╡ рдЬреЛ рдЕрдВрддрд┐рдо рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рд╕рд╛рд░рд╛рдВрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рджреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдХреА рддреБрд▓рдирд╛


рд╣рдореЗрдВ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рджреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдХрд╛рд░реНрдп рд╣реИ рдЬрд┐рд╕рдиреЗ рдореБрдЭреЗ .NET рдореЗрдВ SIMD рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рд╛рдпрд╛ред рдлрд┐рд░, рдЖрдЗрдП рдмреЗрдВрдЪрдорд╛рд░реНрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХрдИ рддрд░реАрдХреЗ рд▓рд┐рдЦреЗрдВ рдФрд░ рджреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: рдПрд░реЗрд░рд╛ рдФрд░ рдЕрд░реНрд░реЗрдмреАред


рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди:


 public bool Naive() { for (int i = 0; i < ArrayA.Length; i++) { if (ArrayA[i] != ArrayB[i]) return false; } return true; } 

LINQ- рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди:


 public bool LINQ() => ArrayA.SequenceEqual(ArrayB); 

MemCmp рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди:


 [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] static extern int memcmp(byte[] b1, byte[] b2, long count); public bool MemCmp() => memcmp(ArrayA, ArrayB, ArrayA.Length) == 0; 

System.Numerics рд╕реЗ рд╡реИрдХреНрдЯрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди:


 public bool Vectors() { int vectorSize = Vector<byte>.Count; int i = 0; for (; i <= ArrayA.Length - vectorSize; i += vectorSize) { var va = new Vector<byte>(ArrayA, i); var vb = new Vector<byte>(ArrayB, i); if (!Vector.EqualsAll(va, vb)) { return false; } } for (; i < ArrayA.Length; i++) { if (ArrayA[i] != ArrayB[i]) return false; } return true; } 

рдЖрдВрддрд░рд┐рдХ рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди:


 public unsafe bool Intrinsics() { int vectorSize = 256 / 8; int i = 0; const int equalsMask = unchecked((int) (0b1111_1111_1111_1111_1111_1111_1111_1111)); fixed (byte* ptrA = ArrayA) fixed (byte* ptrB = ArrayB) { for (; i <= ArrayA.Length - vectorSize; i += vectorSize) { var va = Avx2.LoadVector256(ptrA + i); var vb = Avx2.LoadVector256(ptrB + i); var areEqual = Avx2.CompareEqual(va, vb); if (Avx2.MoveMask(areEqual) != equalsMask) { return false; } } for (; i < ArrayA.Length; i++) { if (ArrayA[i] != ArrayB[i]) return false; } return true; } } 

рдореЗрд░реЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЪрд▓рд╛рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо:


рд╡рд┐рдзрд┐ItemsCountрдореАрдирддреНрд░реБрдЯрд┐StdDevрдЕрдиреБрдкрд╛рдд
рдЕрдиреБрднрд╡рд╣реАрди100007,033.8 рдПрди.рдПрд╕.50.636 рдПрди.рдПрд╕.47.365 рдПрди.рдПрд╕.1.00
LINQ1000064,841.4 рдПрдирдПрд╕289.157 рдПрди.рдПрд╕.270.478 рдПрди.рдПрд╕.9.22
рд╡реИрдХреНрдЯрд░10000504.0 рдПрди.рдПрд╕.реи.рекрежрем рдПрди.рдПрд╕.реи.реирелрез рдПрди.рдПрд╕.0.07
memcmp10000368.1 рдПрди.рдПрд╕.2.637 рдПрди.рдПрд╕.реи.рекремрем рдПрди.рдПрд╕.0.05
intrinsics10000283.6 рдПрдирдПрд╕рез.резрейрел рдПрди.рдПрд╕.1.061 рдПрди.рдПрд╕.0.04
рдЕрдиреБрднрд╡рд╣реАрди10000085,214.4 рдПрди.рдПрд╕.903.868 рдПрди.рдПрд╕.845.478 рдПрдирдПрд╕1.00
LINQ100000702,279.4 рдПрди.рдПрд╕.2,846.609 рдПрди.рдПрд╕.2,662.720 рдПрди.рдПрд╕.8.24
рд╡реИрдХреНрдЯрд░1000005,179.2 рдПрди.рдПрд╕.45.337 рдПрди.рдПрд╕.42.409 рдПрди.рдПрд╕.0.06
memcmp1000004,510.5 рдПрди.рдПрд╕.24.292 рдПрди.рдПрд╕.22.723 рдПрди.рдПрд╕.0.05
intrinsics1000002,957.0 рдПрди.рдПрд╕.11.452 рдПрди.рдПрд╕.10.712 рдПрдирдПрд╕0.03
рдЕрдиреБрднрд╡рд╣реАрди1000000844,006.1 рдПрди.рдПрд╕.3,552.478 рдПрдирдПрд╕3,322.990 рдПрди.рдПрд╕.1.00
LINQ10000006,483,079.3 рдПрдирдПрд╕42,641.040 рдПрди.рдПрд╕.39,886.455 рдПрди.рдПрд╕.7.68
рд╡реИрдХреНрдЯрд░100000054,180.1 рдПрди.рдПрд╕.357.258 рдПрди.рдПрд╕.334.180 рдПрди.рдПрд╕.0.06
memcmp100000049,480.1 рдПрди.рдПрд╕.515.675 рдПрди.рдПрд╕.457.133 рдПрди.рдПрд╕.0.06
intrinsics100000036,633.9 рдПрди.рдПрд╕.680.525 рдПрди.рдПрд╕.636.564 рдПрди.рдПрд╕.0.04

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдХреЛрдб рд╕реНрдкрд╖реНрдЯ рд╣реИ, рджреЛ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЖрдВрддрд░рд┐рдХ рдореЗрдВ:


 var areEqual = Avx2.CompareEqual(va, vb); if (Avx2.MoveMask(areEqual) != equalsMask) { return false; } 

рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдореЗрдВ рджреЛ рд╡реИрдХреНрдЯрд░ рдХреА рд╕рдорд╛рдирддрд╛ рдХреЗ рд▓рд┐рдП рддреБрд▓рдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЗрд░реЗрдХреНрд╡рд▓ рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдмрдЪрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рддрддреНрд╡ рдХреЗ рд╕рднреА рдмрд┐рдЯреНрд╕ 1 рдкрд░ рд╕реЗрдЯ рд╣реЛрддреЗ рд╣реИрдВ рдпрджрд┐ va рдФрд░ vb рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рддрддреНрд╡ рд╕рдорд╛рди рд╣реЛрддреЗ рд╣реИрдВред рддреЛ, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрджрд┐ рдмрд╛рдЗрдЯ рд╡реИрдХреНрдЯрд░ рд╡реИрдм рдФрд░ рд╡реАрдмреА рд╕рдорд╛рди рд╣реИрдВ, рддреЛ рдПрд╕реЗрдХреНрд╡рд╛рд▓реНрд╕ рдХреЗ рд╕рднреА рддрддреНрд╡ 255 (11111111b) рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред рдЬреИрд╕рд╛ рдХрд┐ Avx2.CompareEqual _mm256_cmpeq_epi8 рдкрд░ рдПрдХ рдЖрд╡рд░рдг рд╣реИ, рд╣рдо рдЗрдВрдЯреЗрд▓ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕ рдСрдкрд░реЗрд╢рди рдХреЗ рдЫрджреНрдо рдХреЛрдб рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:
MoveMask рд╡рд┐рдзрд┐ рд╡реЗрдХреНрдЯрд░ рд╕реЗ 32-рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛ рдмрдирд╛рддреА рд╣реИред рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ 32 рдПрдХрдмрд╛рдЗрдЯ рддрддреНрд╡реЛрдВ рдХреЗ рд╢реАрд░реНрд╖ рдмрд┐рдЯреНрд╕ MoveMask рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдмрд┐рдЯреНрд╕ рдХреЗ рдорд╛рди рд╣реИрдВред рд╕реНрдпреВрдбреЛрдХреЛрдб рдпрд╣рд╛рдБ рдЙрдкрд▓рдмреНрдз рд╣реИ ред


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрджрд┐ va рдФрд░ vb рдореЗрдВ рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ areEqual рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдмрд╛рдЗрдЯреНрд╕ 0. рд╣реЛрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдЗрди рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд╢реАрд░реНрд╖ рдмрд┐рдЯреНрд╕ 0 рднреА рд╣реЛрдВрдЧреЗред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ Avx2.MoveMask рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдмрд┐рдЯреНрд╕ 0 рднреА рд╣реЛрдВрдЧреЗ рдФрд░ рдПрд╕реЗрдХреНрд╡рд▓ рдмрд░рд╛рдмрд░ рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред


рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╡реЗрдХреНрдЯрд░ рдХреА рд▓рдВрдмрд╛рдИ 8 рдмрд╛рдЗрдЯреНрд╕ рд╣реИ (рдХрдо рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП):


  • рдЖрдЬреНрдЮрд╛ рджреЗрдирд╛ va = {100, 10, 20, 30, 100, 40, 50, 100} рдФрд░ vb = {100, 20, 10, 30, 100, 40, 80, 90}ред
  • рдлрд┐рд░ рдИрдХреНрд╡рд╛рд▓реНрд╕ {255, 0, 0, 255, 255, 255, 0, 0} рд╣реЛрдВрдЧреЗред
  • MoveMask рд╡рд┐рдзрд┐ 10011100b рд▓реМрдЯреЗрдЧреА рдЬрд┐рд╕рдХреА рддреБрд▓рдирд╛ 11111111b рдорд╛рд╕реНрдХ рд╕реЗ рдХреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдПред рдЪреВрдВрдХрд┐ рдпреЗ рдорд╛рд╕реНрдХ рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП va рдФрд░ vb рд╡реИрдХреНрдЯрд░ рднреА рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИрдВред

рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдПрдХ рддрддреНрд╡ рд╣реЛрдиреЗ рдХреЗ рд╕рдордп рдХреА рдЧрд┐рдирддреАред


рдХрднреА-рдХрднреА рдЖрдкрдХреЛ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рддрддреНрд╡ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬреИрд╕реЗ рдкреВрд░реНрдгрд╛рдВрдХ, рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВред рд╣рдо рдЗрд╕ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рднреА рдЧрддрд┐ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред рддреБрд▓рдирд╛ рдХреЗ рд▓рд┐рдП рдЖрдЗрдП рдРрд░реЗ рдореЗрдВ рдЖрдЗрдЯрдо рддрддреНрд╡ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рддрд░реАрдХреЗ рд▓рд┐рдЦреЗрдВред


рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рдПрдХ:


 public int Naive() { int result = 0; foreach (int i in Array) { if (i == Item) { result++; } } return result; } 

LINQ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛:


 public int LINQ() => Array.Count(i => i == Item); 

System.Numerics.Vectors рд╕реЗ рд╡реИрдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛:


 public int Vectors() { var mask = new Vector<int>(Item); int vectorSize = Vector<int>.Count; var accResult = new Vector<int>(); int i; var array = Array; for (i = 0; i <= array.Length - vectorSize; i += vectorSize) { var v = new Vector<int>(array, i); var areEqual = Vector.Equals(v, mask); accResult = Vector.Subtract(accResult, areEqual); } int result = 0; for (; i < array.Length; i++) { if (array[i] == Item) { result++; } } result += Vector.Dot(accResult, Vector<int>.One); return result; } 

рдЖрдВрддрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛:


 public unsafe int Intrinsics() { int vectorSize = 256 / 8 / 4; var temp = stackalloc int[vectorSize]; for (int j = 0; j < vectorSize; j++) { temp[j] = Item; } var mask = Avx2.LoadVector256(temp); var accVector = Vector256<int>.Zero; int i; var array = Array; fixed (int* ptr = array) { for (i = 0; i <= array.Length - vectorSize; i += vectorSize) { var v = Avx2.LoadVector256(ptr + i); var areEqual = Avx2.CompareEqual(v, mask); accVector = Avx2.Subtract(accVector, areEqual); } } int result = 0; Avx2.Store(temp, accVector); for(int j = 0; j < vectorSize; j++) { result += temp[j]; } for(; i < array.Length; i++) { if (array[i] == Item) { result++; } } return result; } 

рдореЗрд░реЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЪрд▓рд╛рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо:


рд╡рд┐рдзрд┐ItemsCountрдореАрдирддреНрд░реБрдЯрд┐StdDevрдЕрдиреБрдкрд╛рдд
рдЕрдиреБрднрд╡рд╣реАрди108.844 рдПрди.рдПрд╕.0.0772 рдПрди.рдПрд╕.0.0603 рдПрди.рдПрд╕.1.00
LINQ1087.456 рдПрди.рдПрд╕.0.9496 рдПрди.рдПрд╕.0.8883 рдПрди.рдПрд╕.9.89
рд╡реИрдХреНрдЯрд░103.140 рдПрди.рдПрд╕.0.0406 рдПрди.рдПрд╕.0.0380 рдПрди.рдПрд╕.0.36
intrinsics10резрей.резрей рдПрди.рдПрд╕.0.0825 рдПрди.рдПрд╕.0.0772 рдПрди.рдПрд╕.1.56
рдЕрдиреБрднрд╡рд╣реАрди100резреж ..рейрезреж рдПрди.рдПрд╕.0.6975 рдПрди.рдПрд╕.0.6183 рдПрди.рдПрд╕.1.00
LINQ100626.285 рдПрди.рдПрд╕.5.7677 рдПрди.рдПрд╕.5.3951 рдПрди.рдПрд╕.5.83
рд╡реИрдХреНрдЯрд░10011.844 рдПрди.рдПрд╕.0.2113 рдПрди.рдПрд╕.0.1873 рдПрди.рдПрд╕.0.11
intrinsics10019.616 рдПрди.рдПрд╕.0.1018 рдПрди.рдПрд╕.0.0903 рдПрди.рдПрд╕.0.18
рдЕрдиреБрднрд╡рд╣реАрди10001,032.466 рдПрди.рдПрд╕.6.3799 рд░реБрдкрдпреЗ5.6556 рдПрди.рдПрд╕.1.00
LINQ10006,266.605 рдПрди.рдПрд╕.42.6585 рдПрди.рдПрд╕.39.9028 рдПрди.рдПрд╕.6.07
рд╡реИрдХреНрдЯрд░100083.417 рдПрди.рдПрд╕.0.5393 рдПрди.рдПрд╕.0.4780 рдПрди.рдПрд╕.0.08
intrinsics100088.358 рдПрди.рдПрд╕.0.4921 рдПрди.рдПрд╕.0.4603 рдПрди.рдПрд╕.0.09
рдЕрдиреБрднрд╡рд╣реАрди100009,942.503 рдПрди.рдПрд╕.47.9732 рдПрди.рдПрд╕.40.0598 рдПрди.рдПрд╕.1.00
LINQ1000062,305.598 рдПрди.рдПрд╕.643.8775 рдПрди.рдПрд╕.502.6972 рдПрди.рдПрд╕.6.27
рд╡реИрдХреНрдЯрд░10000914.967 рдПрди.рдПрд╕.7.2959 рдПрди.рдПрд╕.6.8246 рдПрди.рдПрд╕.0.09
intrinsics10000931.698 рдПрди.рдПрд╕.6.3444 рдПрди.рдПрд╕.5.9346 рдПрди.рдПрд╕.0.09
рдЕрдиреБрднрд╡рд╣реАрди10000094,834.804 рдПрди.рдПрд╕.793.8585 рдПрди.рдПрд╕.703.7349 рдПрди.рдПрд╕.1.00
LINQ100000626,620.968 рдПрди.рдПрд╕.4,696.9221 рдПрди.рдПрд╕.4,393.5038 рдПрди.рдПрд╕.6.61
рд╡реИрдХреНрдЯрд░1000009,000.827 рдПрди рдПрд╕179.5351 рдПрди.рдПрд╕.192.1005 рдПрди.рдПрд╕.0.09
intrinsics1000008,690.771 рдПрдирдПрд╕101.7078 рдПрдирдПрд╕95.1376 рдПрди.рдПрд╕.0.09
рдЕрдиреБрднрд╡рд╣реАрди1000000959,302.249 рдПрди.рдПрд╕.4,268.2488 рдПрди.рдПрд╕.3,783.6914 рдПрди.рдПрд╕.1.00
LINQ10000006,218,681.888 ns31,321.9277 рдПрди.рдПрд╕.29,298.5506 рдПрди.рдПрд╕.6.48
рд╡реИрдХреНрдЯрд░100000099,778.488 рдПрди.рдПрд╕.1,975.6001 рдПрди.рдПрд╕.4,252.6877 рдПрди.рдПрд╕.0.10
intrinsics100000096,449.350 рдПрди.рдПрд╕.1,171.8067 рдПрди.рдПрд╕.978.5116 рдПрди.рдПрд╕.0.10

рд╡реИрдХреНрдЯрд░ рдФрд░ рдЗрдВрдЯреНрд░рд┐рдВрд╕рд┐рдХреНрд╕ рддрд░реАрдХреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддрд░реНрдХ рдореЗрдВ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рд╡рд┐рд╢реЗрд╖ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рднрд┐рдиреНрди рд╣реЛрддреЗ рд╣реИрдВред рд╡рд┐рдЪрд╛рд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИ:


  • рдорд╛рд╕реНрдХ рд╡реЗрдХреНрдЯрд░ рдмрдирд╛рдПрдВ рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдореЗрдВ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддреА рд╣реИ;
  • v рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдПрдХ рд╕рд░рдгреА рдХреЗ рднрд╛рдЧ рдХреЛ рд▓реЛрдб рдХрд░реЗрдВ рдФрд░ рдЗрд╕ рднрд╛рдЧ рдХреА рддреБрд▓рдирд╛ рдорд╛рд╕реНрдХ рд╕реЗ рдХрд░реЗрдВред рдирддреАрдЬрддрди, рд╕рднреА рдмрд┐рдЯреНрд╕ рдПрд╕реЗрдХреНрд╡рд╛рд▓ рдХреЗ рд╕рдорд╛рди рддрддреНрд╡реЛрдВ рдореЗрдВ рд╕реЗрдЯ рд╣реЛ рдЬрд╛рдПрдВрдЧреЗред рдЬреИрд╕рд╛ рдХрд┐ рдИрдХреНрд╡рд▓ рдкреВрд░реНрдгрд╛рдВрдХ рдХрд╛ рдПрдХ рд╕рд░рдгреА рд╣реИ, рддреЛ рдпрджрд┐ рд╣рдо рдПрдХ рддрддреНрд╡ рдХреЗ рд╕рднреА рдмрд┐рдЯреНрд╕ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЗрд╕ рддрддреНрд╡ рдореЗрдВ -1 рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ ((рдЗрдВрдЯ) (1111_1111_1111_1111_1111_1111_1111_1111b) == -1);
  • рдПрдХреНрд╡реАрдХреНрдЯрд░ рд╕реЗ рдШрдЯрд╛рд╡ рд╡реЗрдХреНрдЯрд░ рд╡реЗрдХреНрдЯрд░ рд╣реИрдВред рдлрд┐рд░, accVector рдкреНрд░рддреНрдпреЗрдХ рдкрдж рдХреЗ рд▓рд┐рдП рд╕рднреА v рд╡реИрдХреНрдЯрд░реЛрдВ рдореЗрдВ рдЖрдЗрдЯрдо рддрддреНрд╡ рдХрд┐рддрдиреА рдмрд╛рд░ рд╣реБрдЖ рдЗрд╕рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдЧрд╛ (рд╢реВрдиреНрдп рд╕реЗ рдЛрдг рдПрдХ рдкреНрд▓рд╕ рд╣реИ)ред

рд▓реЗрдЦ рдХрд╛ рдкреВрд░рд╛ рдХреЛрдб GitHub рдкрд░ рд╣реИ ред


рдирд┐рд╖реНрдХрд░реНрд╖


рдореИрдВрдиреЗ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рди рд╡реИрд╢реНрд╡реАрдХрд░рдг рдХреЗ рд▓рд┐рдП .NET рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдХреЗрд╡рд▓ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╣рд┐рд╕реНрд╕рд╛ рдмрддрд╛рдпрд╛ред .NET Core рдХреЗ рддрд╣рдд рдЙрдкрд▓рдмреНрдз рд╕рднреА рдЖрдВрддрд░рд┐рдХ рдХреА рдкреВрд░реНрдг рдЕрджреНрдпрддрди рд╕реВрдЪреА рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, x рд╕реНрд░реЛрдд рдХреЛрдб рдкрд░ рдЬрд╛рдПрдВ ред рдпрд╣ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдХрд┐ C # рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЖрдВрддрд░рд┐рдХ рдХрд╛ рд╕рд╛рд░рд╛рдВрд╢ C рджреБрдирд┐рдпрд╛ рдореЗрдВ рдЕрдкрдирд╛ рдирд╛рдо рд░рдЦрддрд╛ рд╣реИред рдпрд╣ рдпрд╛ рддреЛ рдЗрд╕ рдЖрдВрддрд░рд┐рдХ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдФрд░ рдореМрдЬреВрджрд╛ C ++ / C рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ .NET рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред System.Numerics.Vector рдкреНрд░рд▓реЗрдЦрди msdn рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ .NET рдХрд╛ C ++ рдкрд░ рдмрд╣реБрдд рдлрд╛рдпрджрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреНрд▓рд╛рдЗрдВрдЯ рдорд╢реАрди рдкрд░ рд╣реЛрддрд╛ рд╣реИ, рдПрдХ рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдХреНрд▓рд╛рдЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рдЕрдзрд┐рдХрддрдо рдкреНрд░рджрд░реНрд╢рди рджреЗ рд╕рдХрддрд╛ рд╣реИред рдЙрд╕реА рд╕рдордп, рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдлрд╛рд╕реНрдЯ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рднрд╛рд╖рд╛ рдФрд░ рдПрдХ рд╣реА рддрдХрдиреАрдХреЛрдВ рдХреЗ рднреАрддрд░ рд░рд╣ рд╕рдХрддрд╛ рд╣реИред

Source: https://habr.com/ru/post/hi467689/


All Articles