рдпрд╣рд╛рдБ .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 рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХрд┐рдпрд╛ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП:
рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рдФрд░ 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; }
рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рд╡реИрдХреНрдЯрд░ рдХреА рддрд░рд╣ рд╣реИ:
рджреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдХреА рддреБрд▓рдирд╛
рд╣рдореЗрдВ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рджреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдХрд╛рд░реНрдп рд╣реИ рдЬрд┐рд╕рдиреЗ рдореБрдЭреЗ .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; } }
рдореЗрд░реЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЪрд▓рд╛рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо:
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдХреЛрдб рд╕реНрдкрд╖реНрдЯ рд╣реИ, рджреЛ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЖрдВрддрд░рд┐рдХ рдореЗрдВ:
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; }
рдореЗрд░реЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЪрд▓рд╛рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо:
рд╡реИрдХреНрдЯрд░ рдФрд░ рдЗрдВрдЯреНрд░рд┐рдВрд╕рд┐рдХреНрд╕ рддрд░реАрдХреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддрд░реНрдХ рдореЗрдВ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рд╡рд┐рд╢реЗрд╖ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рднрд┐рдиреНрди рд╣реЛрддреЗ рд╣реИрдВред рд╡рд┐рдЪрд╛рд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИ:
- рдорд╛рд╕реНрдХ рд╡реЗрдХреНрдЯрд░ рдмрдирд╛рдПрдВ рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдореЗрдВ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддреА рд╣реИ;
- 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 ++ рдкрд░ рдмрд╣реБрдд рдлрд╛рдпрджрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреНрд▓рд╛рдЗрдВрдЯ рдорд╢реАрди рдкрд░ рд╣реЛрддрд╛ рд╣реИ, рдПрдХ рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдХреНрд▓рд╛рдЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рдЕрдзрд┐рдХрддрдо рдкреНрд░рджрд░реНрд╢рди рджреЗ рд╕рдХрддрд╛ рд╣реИред рдЙрд╕реА рд╕рдордп, рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдлрд╛рд╕реНрдЯ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рднрд╛рд╖рд╛ рдФрд░ рдПрдХ рд╣реА рддрдХрдиреАрдХреЛрдВ рдХреЗ рднреАрддрд░ рд░рд╣ рд╕рдХрддрд╛ рд╣реИред