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

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


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


рдереЛрдбрд╝рд╛ рд╕рд╛ рдЗрддрд┐рд╣рд╛рд╕


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


рд╕рд░рдгреА рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд▓рд┐рдЦреЗрдВ


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


рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реИ


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рдордВрдЭрд▓рд╛
рдЕрдиреБрднрд╡рд╣реАрди1075.12 рдПрди.рдПрд╕.
LINQ101 186.85 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░1060.09 рдПрди.рдПрд╕.
intrinsics10255.40 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди100360.56 рдПрди.рдПрд╕.
LINQ1002 719.24 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░10060.09 рдПрди.рдПрд╕.
intrinsics100345.54 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди10001 847.88 рдПрди.рдПрд╕.
LINQ100012 033.78 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░1000240.38 рдПрди.рдПрд╕.
intrinsics1000630.98 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди1000018 403.72 рдПрди.рдПрд╕.
LINQ10000102 489.96 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░100007 316.42 рдПрди.рдПрд╕.
intrinsics100003 365.25 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди100000176 630.67 рдПрди.рдПрд╕.
LINQ100000975 998.24 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░10000078 828.03 рдПрдирдПрд╕
intrinsics10000041 269.41 рдПрди.рдПрд╕.

рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╡реИрдХреНрдЯрд░ рдФрд░ рдЗрдВрдЯреНрд░рд┐рдВрд╕рд┐рдХреНрд╕ рдХреЗ рд╕рдорд╛рдзрд╛рди рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдФрд░ 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); - рдбреЗрдЯрд╛ рдХреЛ рдЗрдВрдбреЗрдХреНрд╕ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реБрдП, рд╕рд░рдгреА рд╕реЗ, рдПрдХ рдирдпрд╛ рд╡реЗрдХреНрдЯрд░ рд╡реА рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡реЗрдХреНрдЯрд░рд╕рд╛рдЗрдЬрд╝ рдбреЗрдЯрд╛ рд▓реЛрдб рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
  • accVector = Vector.Add (accVector, v); - рджреЛ рд╡реИрдХреНрдЯрд░ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВред
    рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдРрд░реЗ 8 рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ: {0, 1, 2, 3, 4, 5, 6, 7} рдФрд░ рд╡реЗрдХреНрдЯрд░рд╕рд╛рдЗрдЬ == 4, рдлрд┐рд░:
    рд▓реВрдк accVector рдХреЗ рдкрд╣рд▓реЗ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдореЗрдВ = {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 рдЕрд╕реНрдерд╛рдпреА = рд╕реНрдЯреИрдХрд▓реЛрдХ рдЗрдВрдЯ [рд╡реЗрдХреНрдЯрд░рд╕рд╛рдЗрдЬрд╝];
    • рд╡реЗрдХреНрдЯрд░ рдХреЛ рдЗрд╕ рд╕рд░рдгреА рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: Avx2.Store (рдЕрд╕реНрдерд╛рдпреА, accVector);
    • рдПрдХ рд▓реВрдк рдореЗрдВ рдРрд░реЗ рдХреЗ рддрддреНрд╡ рд╕рдореНтАНрдорд┐рд▓рд┐рдд рд╣реИрдВред
  • рдлрд┐рд░ рдЕрдВрддрд┐рдо рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рдирд╣реАрдВ рд░рдЦреА рдЧрдИ рд╕рд░рдгреА рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ

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


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


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


 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рдордВрдЭрд▓рд╛
рдЕрдиреБрднрд╡рд╣реАрди1000066 719.1 рдПрди.рдПрд╕.
LINQ1000071 211.1 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░100003 695.8 рдПрдирдПрд╕
memcmp10000600.9 рдПрди.рдПрд╕.
intrinsics100001 607.5 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди100000588 633.7 рдПрдирдПрд╕
LINQ100000651 191.3 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░10000034 659.1 рдПрди.рдПрд╕.
memcmp1000005 513.6 рдПрдирдПрд╕
intrinsics10000012,078.9 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди10000005 637 293.1 рдПрди.рдПрд╕.
LINQ10000006 622 666.0 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░1000000777 974.2 рдПрди.рдПрд╕.
memcmp1000000361 704.5 рдПрди.рдПрд╕.
intrinsics1000000рекрейрек реирелреи. n рдПрди.рдПрд╕.

рдЗрди рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рднреА рдХреЛрдб, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдЖрдВрддрд░рд┐рдХ рдореЗрдВ рджреЛ рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде:


 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 рдПрдХрд▓-рдмрд╛рдЗрдЯ рддрддреНрд╡реЛрдВ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рдЙрдЪреНрдЪ рдмрд┐рдЯреНрд╕ рд╣реИрдВред рд╕реНрдпреВрдбреЛрдХреЛрдб рдпрд╣рд╛рдБ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрджрд┐ va рдФрд░ vb рдореЗрдВ рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╕рдорд╛рдиреНрдп рдореЗрдВ рдмрд╛рдЗрдЯреНрд╕ 0 рд╣реЛрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдЗрди рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯреНрд╕ рднреА 0 рд╣реЛрдВрдЧреЗ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ Avx2 .Mask рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдмрд┐рдЯреНрд╕ рднреА 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} рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛;
  • рдореВрд╡рдорд╕реНрдХ рд╡рд┐рдзрд┐ 10011100 рдмреА рд▓реМрдЯреЗрдЧреА, рдЬрд┐рд╕реЗ рдорд╛рд╕реНрдХ 11111111 рдмреА рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдХреНрдпреЛрдВрдХрд┐ рдЪреВрдВрдХрд┐ рдпреЗ рдореБрдЦреМрдЯреЗ рдЕрд╕рдорд╛рди рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╡реИрдХреНрдЯрд░ 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 mask = Avx2.SetAllVector256(Item); //var mask = Avx2.SetVector256(Item, Item, Item, Item, Item, Item, Item, Item); 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рдордВрдЭрд▓рд╛
рдЕрдиреБрднрд╡рд╣реАрди10002 824.41 рдПрди.рдПрд╕.
LINQ100012 138.95 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░1000961.50 рдПрди.рдПрд╕.
intrinsics1000691.08 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди1000027 072.25 рдПрди.рдПрд╕.
LINQ10000113 967.87 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░100007 571.82 рдПрди.рдПрд╕.
intrinsics100004,296.71 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди100000361 028.46 рдПрди.рдПрд╕.
LINQ1000001,091,994.28 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░10000082 839.29 рдПрди.рдПрд╕.
intrinsics10000040 307.91 рдПрди.рдПрд╕.
рдЕрдиреБрднрд╡рд╣реАрди10000001 634 175.46 рдПрди.рдПрд╕.
LINQ10000006 194 257.38 рдПрди.рдПрд╕.
рд╡реИрдХреНрдЯрд░1000000583 901.29 рдПрди.рдПрд╕.
intrinsics1000000413 520.38 рдПрди.рдПрд╕.

рд╡реИрдХреНрдЯрд░ рдФрд░ рдЗрдВрдЯреНрд░рд┐рдирд┐рдХреНрд╕ рд╡рд┐рдзрд┐рдпрд╛рдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддрд░реНрдХ рдореЗрдВ рд╕рдорд╛рди рд╣реИрдВ, рдЕрдВрддрд░ рдХреЗрд╡рд▓ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╣реИрдВред рд╕рдордЧреНрд░ рд░реВрдк рдореЗрдВ рд╡рд┐рдЪрд╛рд░ рд╣реИ:


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

рд▓реЗрдЦ рдХреЗ рд╕рднреА рдХреЛрдб GitHub рдкрд░ рджреЗрдЦреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ


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


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


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


UPD (09/15/2019):


рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдореЗрдВ рдПрдХ рдЬрд╛рдо рдерд╛

рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдореЗрдВ, рдореИрдВрдиреЗ IterationSetup рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдЬреЛ рдХрд┐, рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдирд┐рдХрд▓рд╛, рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ 100ms рд╕реЗ рдХрдо рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдЗрд╕реЗ GlobalSetup рдкрд░ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рддрд░рд╣ рд╣реЛрдВрдЧреЗред


рд╕рд░рдгреА рддрддреНрд╡реЛрдВ рдХрд╛ рдпреЛрдЧ:


рд╡рд┐рдзрд┐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

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


рд╡рд┐рдзрд┐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

рдХрд┐рд╕реА рд╕рд░рдгреА рдореЗрдВ рдХрд┐рд╕реА рддрддреНрд╡ рдХреЗ рд╣реЛрдиреЗ рдХреА рд╕рдВрдЦреНрдпрд╛:


рд╡рд┐рдзрд┐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

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


All Articles