.NET Framework 4.8下用SIMD优化double点积及ChainRule函数性能
双精度点积SIMD加速及有序列表并集计算优化问题
我希望用SIMD加速以下双精度点积计算:
[MethodImpl(MethodImplOptions.AggressiveInlining)] static double Dot(double x1, double x2, double y1, double y2) { return x1 * y1 + x2 * y2; }
已知Vector2.Dot仅支持float类型,且无法切换到.NET Core,因此不能使用Vector128.Create(double e0, double e1)来实现双精度SIMD点积。
上述Dot方法用于计算两个有序ID列表的并集,核心逻辑在以下ChainRule函数中:
static void ChainRule(int x_n, int[] x_id, double[] x_jacobi, double x_diff, int y_n, int[] y_id, double[] y_jacobi, double y_diff, out int z_n, out int[] z_id, out double[] z_jacobi) { int n = x_n + y_n; z_id = new int[n]; z_jacobi = new double[n]; int i = 0, ix = 0, iy = 0; while (ix < x_n && iy < y_n) { if (x_id[ix] < y_id[iy]) { z_id[i] = x_id[ix]; z_jacobi[i++] = x_diff * x_jacobi[ix++]; } else if (y_id[iy] < x_id[ix]) { z_id[i] = y_id[iy]; z_jacobi[i++] = y_diff * y_jacobi[iy++]; } else { z_id[i] = x_id[ix]; z_jacobi[i++] = Dot(x_diff, y_diff, x_jacobi[ix++], y_jacobi[iy++]); } } while (ix < x_n) { z_id[i] = x_id[ix]; z_jacobi[i++] = x_diff * x_jacobi[ix++]; } while (iy < y_n) { z_id[i] = y_id[iy]; z_jacobi[i++] = y_diff * y_jacobi[iy++]; } z_n = i; }
我曾尝试预计算x_diff与x_jacobi、y_diff与y_jacobi的乘积,代码如下:
double[] x_diff_jacobi = new double[x_n]; for (int i0 = 0; i0 < x_n; i0++) x_diff_jacobi[i0] = x_diff * x_jacobi[i0]; double[] y_diff_jacobi = new double[y_n]; for (int i0 = 0; i0 < y_n; i0++) y_diff_jacobi[i0] = y_diff * y_jacobi[i0];
这样可以将交集处的计算简化为z_jacobi[i++] = x_diff_jacobi[ix++] + y_diff_jacobi[iy++],但实际运行速度比原代码更慢,推测是额外数组的初始化和内存分配带来了开销。
请问还有其他优化这段代码的思路吗?
内容的提问来源于stack exchange,提问作者Wollmich
相关产品推荐
相关产品推荐

