在.NET framework 4.6中使用C#中的SIMD操作速度较慢
我目前正在尝试使用C#计算一个巨大数组中所有值的总和,并使用SIMD比较性能,SIMD版本的速度要慢得多。请参阅下面的代码片段,如果我遗漏了什么,请告诉我。“VAL”是一个巨大的数组,它从图像文件中读取并省略该部分以保持精简在.NET framework 4.6中使用C#中的SIMD操作速度较慢,c#,.net,ryujit,C#,.net,Ryujit,我目前正在尝试使用C#计算一个巨大数组中所有值的总和,并使用SIMD比较性能,SIMD版本的速度要慢得多。请参阅下面的代码片段,如果我遗漏了什么,请告诉我。“VAL”是一个巨大的数组,它从图像文件中读取并省略该部分以保持精简 var watch1 = new Stopwatch(); watch1.Start(); var total = vals.Aggregate(0, (a, i) => a + i); watch1.Stop(); Console.WriteLine(string.
var watch1 = new Stopwatch();
watch1.Start();
var total = vals.Aggregate(0, (a, i) => a + i);
watch1.Stop();
Console.WriteLine(string.Format("Total is: {0}", total));
Console.WriteLine(string.Format("Time taken: {0}", watch1.ElapsedMilliseconds));
var watch2 = new Stopwatch();
watch2.Start();
var sTotal = GetSIMDVectors(vals).Aggregate((a, i) => a + i);
int sum = 0;
for (int i = 0; i < Vector<int>.Count; i++)
sum += sTotal[i];
watch2.Stop();
Console.WriteLine(string.Format("Another Total is: {0}", sum));
Console.WriteLine(string.Format("Time taken: {0}", watch2.ElapsedMilliseconds));
var watch1=新秒表();
watch1.Start();
var total=价值合计(0,(a,i)=>a+i);
watch1.Stop();
WriteLine(string.Format(“Total是:{0}”,Total));
WriteLine(string.Format(“花费的时间:{0}”,watch1.elapsedmillesons));
var watch2=新秒表();
watch2.Start();
var sTotal=GetSimdVector(VAL).聚合((a,i)=>a+i);
整数和=0;
对于(int i=0;i
以及GetSIMDVectors方法
private static IEnumerable<Vector<int>> GetSIMDVectors(short[] source)
{
int vecCount = Vector<int>.Count;
int i = 0;
int len = source.Length;
for(i = 0; i + vecCount < len; i = i + vecCount)
{
var items = new int[vecCount];
for (int k = 0; k < vecCount; k++)
{
items[k] = source[i + k];
}
yield return new Vector<int>(items);
}
var remaining = new int[vecCount];
for (int j = i, k =0; j < len; j++, k++)
{
remaining[k] = source[j];
}
yield return new Vector<int>(remaining);
}
私有静态IEnumerable GetSimdVector(短[]源代码)
{
int vecCount=Vector.Count;
int i=0;
int len=源文件的长度;
对于(i=0;i+vecCount
正如@mike z所指出的,您需要确保您处于发布模式,并且以64位为目标,否则支持SIMD的编译器RuyJIT将无法工作(目前,它仅在64位体系结构上受支持)。
此外,在执行前进行检查始终是一种良好的做法,使用:
Vector.IsHardwareAccelerated;
另外,在创建向量之前,不需要先使用for循环来创建数组。您只需使用向量(int[]array,int index)
构造函数从原始源数组创建向量即可
yield return new Vector<int>(source, i);
我的性能只提高了1.5倍。考虑到操作的简单性,对于这个非常特殊的情况,仍然是一个改进
不用说,矢量化版本需要大型阵列来克服每次迭代中创建
新Vector()
所带来的开销。您是否在64位(即释放模式)和64位(确保您没有使用任何32位CPU)上运行优化?您可以通过验证SIMD是否正在使用。就是这样。没有在64位模式下运行。迈克,如果你发布一个答案,我可以这样标记
var items = new int[vecCount];
for (int k = 0; k < vecCount; k++)
{
items[k] = source[i + k];
}
yield return new Vector<int>(items);
private static int GetSIMDVectorsSum(int[] source)
{
int vecCount = Vector<int>.Count;
int i = 0;
int end_state = source.Length;
Vector<int> temp = Vector<int>.Zero;
for (; i < end_state; i += vecCount)
{
temp += new Vector<int>(source, i);
}
return Vector.Dot<int>(temp, Vector<int>.One);
}
private static int no_vec_sum(int[] vals)
{
int end = vals.Length;
int temp = 0;
for (int i = 0; i < end; i++)
{
temp += vals[i];
}
return temp;
}