有没有更快的方法在安全模式下遍历数组

本文关键字:安全模式 遍历 数组 方法 有没有 | 更新日期: 2023-09-27 18:15:20

我正在编写一个测量采样正弦波频率的方法。它需要一个较大的1D数组(10^3到10^4个采样数量级)并返回double。在方法体中还调用一个辅助方法,该方法检查波是否越过零。下面是我写的一个例子:

public static double Hertz(float[] v, int n) {
    int nZCros = 0
    for (int i = 1; i < n; i++) {
        if (IsZeroCrossing(v.Skip(i - 1).ToArray())) {
            ++nZCros;
        }
    }
    return (double)nZCros / 2.0;
}
private static bool IsZeroCrossing(float[] v) {
    bool cross;
    //checks if the first two elements of the array are opposite sign or not
    return cross;
}

我的问题是该方法需要200-300毫秒来运行。所以我决定尝试使用unsafe和指针,像这样,

public unsafe static double Hertz(float* v, int n) {
    int nZCros = 0
    for (int i = 1; i < n; i++) {
        if (IsZeroCrossing(&v[i - 1])) {
            ++nZCros;
        }
    }
    return (double)nZCros / 2.0;
}
private unsafe static bool IsZeroCrossing(float* v) {
    bool cross;
    //checks if the first two elements of the array are opposite sign or not
    return cross;
}

运行时间2-4毫秒

然而,我真的不愿意冒险超出推荐的范围。有没有办法在安全的情况下达到同样的速度?如果没有,它是否违背了使用c#的目的?我真的应该在这些信号处理应用程序和科学实现中使用c#吗?

这只是我正在编写的许多DSP方法之一,这些方法采用大量样本作为输入。但是这一个让我意识到有一个问题,因为我在测试这个方法时不小心放入了48000个样本而不是4800个,它花了20秒才返回一个值。

谢谢。

UPDATE:我尝试在前面的代码片段中添加Take(2)后的Skip(i - 1)。这将它降低到90-100毫秒,但问题仍然存在。

有没有更快的方法在安全模式下遍历数组

不需要将数组元素的副本传递给IsZeroCrossing()

相反,只需传递您感兴趣的两个元素:

private static bool IsZeroCrossing(float elem1, float elem2)
{
    return elem1*elem2 < 0.0f; // Quick way to check if signs differ.
}

然后这样命名:

if (IsZeroCrossing(v[i-1], v[i]) {

有可能这样一个简单的方法将被内联到一个发布版本中,使其尽可能快。