我试图在我的函数中使用 SIMD 来提高性能,但似乎在内存中的数据准备过程中我丢失了更多。
我有什么:
public class SubProp
{
public double subProp1, subProp2;
<few functions>
}
public class MyClass
{
public subProp prop1, prop2;
<lots of other props>
}
public void DoSomeMath(List<MyClass> data)
{
int cnt = data.Count;
for(int i = 0; i < cnt; i++)
{
SubProp Prop1 = data[i].prop1;
SubProp Prop2 = data[i].prop2
for(int j = i + 1; j < cnt; j++)
{
SubProp Prop3 = data[j].prop1;
SubProp Prop4 = data[j].prop2;
//these substructions suppose to be optimized with SIMD
double res1 = Prop4.subProp2 - Prop3.subProp2;
double res2 = Prop1.subProp1 - Prop2.subProp1;
double res3 = Prop4.subProp1 - Prop3.subProp1;
double res4 = Prop1.subProp2 - Prop2.subProp2;
double res5 = Prop4.subProp1 - Prop2.subProp1;
double res6 = Prop4.subProp2 - Prop2.subProp2;
<some more math with res<n> variables and logical functions on results>
}
}
}
我已经尝试过的:
我错过了什么吗?某种以正确顺序在内存中设置数据的快速方法,或者在这种情况下甚至不可能使用 SIMD 获得更好的性能?
附言关于我如何在这里使用 Vector256 的一些解释:
var lSide, rSide //prepared arrays or spans
int vectorSize = 256 / 8 / 8;
fixed (double* lptr = lSide)
{
fixed (double* rptr = rSide)
{
for (i = 0; i < array.Length - vectorSize; i += vectorSize) {
var lVec = Avx2.LoadVector256(lptr);
var rVec = Avx2.LoadVector256(rptr);
resVector = Avx2.Subtract(lVec, rVec);
.....
}
}
}
附注
似乎我无法将类的 2 个字段的字段一一放入内存中:
[StructLayout(LayoutKind.Explicit)]
public sealed class SubProp
{
[FieldOffset(0)] public double subProp1;
[FieldOffset(8)] public double subProp2;
public double Sum() //just simple function for the test
{
return subProp1 + subProp2;
}
}
[StructLayout(LayoutKind.Explicit)]
public sealed class MyClass
{
[FieldOffset(0)] public SubProp prop1;
[FieldOffset(16)] public SubProp prop2;
}
MyClass testObj = new MyClass
{
prop1 = new SubProp
{
subProp1 = 10,
subProp2 = 20
},
prop2 = new SubPorp
{
subProp1 = 30,
subProp2 = 40
}
};
fixed(double* ptr = &testObj.prop1.subProp1)
{
for(int i=0; i<4; i=i+1)
{
Console.WriteLine(*(ptr+i));
}
}
输出是:
10
20
0
<garbage>
最佳答案
我将有三个想法来优化您的代码:
1.:以下两个操作:
double res1 = data[i].prop2.subProp2 - data[j].prop1.subProp1;
double res2 = data[j].prop1.subProp1 - data[i].prop2.subProp2;
也可以写成:
double res1 = data[i].prop2.subProp2 - data[j].prop1.subProp1;
double res2 = res1 * -1; // or double res2 = -res1; Thanks to Peter Cordes for that hint...
可能的情况:
a = 5, b = 3:a - b = 2 和 b - a = -2
a = 3,b = 0:a - b = 3 和 b - a = -3
a = 0,b = 0:a - b = 0 和 b - a = 0
a = 3, b = -2: a - b = 5 和 b - a = -5
虽然我必须承认,我不知道那是否更快......
2.:您可能会使用 Parallel.For 而不是您的 for 循环。如果您不在下一次迭代中使用一次迭代的结果,这将是可能的。
3.:您多次访问您的属性。根据您执行此操作的频率,在本地存储它们可能会有好处。特别是那些通过 i 计数器访问的。
for(int i = 0; i < cnt; i++)
{
SubProp dataIProp1 = data[i].prop1;
SubProp dataIProp2 = data[i].prop2;
for(int j = i + 1; j < cnt; j++)
{
//these substructions suppose to be optimized with SIMD
double res1 = dataIProp2.subProp2 - data[j].prop1.subProp1;
...
关于c# - 在 c# 中为 Vector256 准备数据的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61363547/