从数组中分离数据的快速方法

问题描述 投票:0回答:2

我有一个包含一些数据的 int 数组。该阵列从 4 通道设备收集数据。

按设备的数组每秒填充如下:(数据约为 200000 个数字

int[] data = new data[]{1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,...};
//data[0] received from Channel 0
//data[1] received from Channel 1 
//data[2] received from Channel 2 
//data[3] received from Channel 3
//data[4] received from Channel 0
//data[5] received from Channel 1 
//data[6] received from Channel 2 
//data[7] received from Channel 3
// to end...

并结束。每一秒之后我都必须分离通道的数据进行处理。

为了分离每个通道,我使用以下代码:

double[] ai1 = new double[data.Length/4];
double[] ai2 = new double[data.Length/4];
double[] ai3 = new double[data.Length/4];
double[] ai4 = new double[data.Length/4];
for (int i = 0; i < data.Length/4; i++)
{
    ai1[i] = data[i * 4 + 0];
    ai2[i] = data[i * 4 + 1];
    ai3[i] = data[i * 4 + 2];
    ai4[i] = data[i * 4 + 3];
}

有什么快速的方法可以将这个数组分成四个子数组吗?

更新:

我使用“Parallel.For”,在我的计算机上大约需要 0.02ms。 但如果我使用简单的“for”,大约需要0.001ms

 double[] ai1 = new double[data.Length / 4];
 double[] ai2 = new double[data.Length / 4];
 double[] ai3 = new double[data.Length / 4];
 double[] ai4 = new double[data.Length / 4];
 Parallel.For(0, data.Length / 4, i =>
 {
     ai1[i] = data[i * 4 + 0];
     ai2[i] = data[i * 4 + 1];
     ai3[i] = data[i * 4 + 2];
     ai4[i] = data[i * 4 + 3];
 });
c# arrays
2个回答
1
投票

这段代码足够高效吗?

我们该如何辨别?您的性能要求/期望是什么?

优化的第一条规则是从测量开始。如果你不知道你的方法需要多长时间,你就不知道你是否做出了任何改进。分析您的应用程序也是一个好主意,因此您可以比较此方法与其他方法的成本。优化只占运行时间 1% 的方法可能没有什么意义。

如果你的方法需要 0.001ms 或 1us,那么进行任何优化可能没什么意义,除非每秒也调用数千次。

尽管如此,示例代码并没有出现很大的低效率问题。您可以使用类似

Parallel.For
之类的工具将计算分散到更多核心上,但这只有在您有空闲核心可用时才有帮助。它也有一些开销,因此只有当您有足够的数据可供处理时才会有帮助。您可能还需要手动分区数据以减少调用委托的开销。

更先进的解决方案是使用SIMD。主要思想是从源加载 4 个向量,然后blend这些向量以在向量之间移动所有值,因此每个向量仅包含来自一个通道的值,然后对向量进行打乱以再次将值按正确的顺序排列。 使用 SIMD 在 C 中将 AoS 转换为 SoA 包括在 C 中使用 SSE 实现 3 个独立通道的示例。 SIMD的优点是可以更好地利用CPU资源。缺点是代码要复杂得多,而且并非所有 CPU 都支持相同的 SIMD 指令,因此您可能需要后备。

AoS 代表“结构数组”,即您的原始数据。而 SoA 代表“数组结构”,即您想要的。


0
投票

真的有必要获取第一个数组中的数据吗?因为如果没有,您可以首先使用 4 个单独的数组来获取数据,这样您就不必每秒循环每个数据。

© www.soinside.com 2019 - 2024. All rights reserved.