是否有更快的方法在安全模式下循环数组

时间:2016-10-28 13:57:53

标签: c# arrays pointers unsafe

我正在编写一种测量采样正弦波频率的方法。它需要一个稍大的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秒。

谢谢。

更新:我尝试在之前的代码段Take(2)之后添加Skip(i - 1)。这使它降至90-100毫秒,但问题仍然存在。

1 个答案:

答案 0 :(得分:3)

您不需要将数组元素的副本传递给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]) {

可能会为发布版本内联这样一个简单的方法,使其尽可能快。