gpt4 book ai didi

c# - 为什么我会看到使用 native 代码的速度提高了约 20%?

转载 作者:IT王子 更新时间:2023-10-29 04:24:34 25 4
gpt4 key购买 nike

知道为什么这段代码:

extern "C" __declspec(dllexport) void Transform(double x[], double y[], int iterations, bool forward)
{
long n, i, i1, j, k, i2, l, l1, l2;
double c1, c2, tx, ty, t1, t2, u1, u2, z;

/* Calculate the number of points */
n = (long)pow((double)2, (double)iterations);

/* Do the bit reversal */
i2 = n >> 1;
j = 0;
for (i = 0; i < n - 1; ++i)
{
if (i < j)
{
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}

/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l = 0; l < iterations; ++l)
{
l1 = l2;
l2 <<= 1;
u1 = 1;
u2 = 0;
for (j = 0; j < l1; j++)
{
for (i = j; i < n; i += l2)
{
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (forward)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}

/* Scaling for forward transform */
if (forward)
{
for (i = 0; i < n; ++i)
{
x[i] /= n;
y[i] /= n;
}
}
}

运行速度比这段代码快 20%?

public static void Transform(DataSet data, Direction direction)
{
double[] x = data.Real;
double[] y = data.Imag;
data.Direction = direction;
data.ExtremeImag = 0.0;
data.ExtremeReal = 0.0;
data.IndexExtremeImag = 0;
data.IndexExtremeReal = 0;

long n, i, i1, j, k, i2, l, l1, l2;
double c1, c2, tx, ty, t1, t2, u1, u2, z;

/* Calculate the number of points */
n = (long)Math.Pow(2, data.Iterations);

/* Do the bit reversal */
i2 = n >> 1;
j = 0;
for (i = 0; i < n - 1; ++i)
{
if (i < j)
{
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}

/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l = 0; l < data.Iterations; ++l)
{
l1 = l2;
l2 <<= 1;
u1 = 1;
u2 = 0;
for (j = 0; j < l1; j++)
{
for (i = j; i < n; i += l2)
{
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = Math.Sqrt((1.0 - c1) / 2.0);
if (direction == Direction.Forward)
c2 = -c2;
c1 = Math.Sqrt((1.0 + c1) / 2.0);
}

/* Scaling for forward transform */
if (direction == Direction.Forward)
{
for (i = 0; i < n; ++i)
{
x[i] /= n;
y[i] /= n;
if (Math.Abs(x[i]) > data.ExtremeReal)
{
data.ExtremeReal = x[i];
data.IndexExtremeReal = (int)i;
}
if (Math.Abs(y[i]) > data.ExtremeImag)
{
data.ExtremeImag = y[i];
data.IndexExtremeImag = (int)i;
}
}
}
}

FFT http://www.rghware.com/fft.png

我通过在我的应用程序中选择“ native DLL FFT”创建了图表中间看到的 CPU 下降:

http://www.rghware.com/InstrumentTuner.zip (源代码)

我认为这将在大多数 PC 上运行。您需要安装 DirectX。我在使用某些硬件的捕获设置时遇到了一些问题。捕获设置本应是可配置的,但该应用的开发却因这一有趣的发现而受到影响。

无论如何,为什么我看到使用 native 代码的速度提高了 20%?这似乎与我之前的一些假设背道而驰。

更新

将函数转换为不安全的方法并修复 long/int 问题后。新的不安全方法实际上比本地方法运行得更快(非常酷)。

Profile http://www.rghware.com/profile.png

很明显,数组边界检查是导致此 FFT 方法速度降低 20% 的原因。由于其性质,无法优化此方法中的 for 循环。

感谢大家的帮助。

最佳答案

仅查看这段代码,根据我的经验,我怀疑从 C++ -> C# 会出现相当显着的减速。

在将这样的例程移植到 C# 时,您将面临的一个主要问题是 C# 将在此处对每个数组检查添加边界检查。由于您永远不会以优化的方式遍历数组 ( see this question for details ),几乎每个数组访问都会接受边界检查。

此外,这个端口非常接近来自 C 的 1->1 映射。如果你通过一个好的 .NET 分析器运行它,你可能会发现一些可以优化的好点,使它回到接近通过一两次调整提高 C++ 速度(这几乎一直是我移植此类例程的经验)。

但是,如果您想让它以几乎相同的速度运行,您可能需要将其转换为不安全的代码并使用指针操作而不是直接设置数组。这将消除所有边界检查问题,并恢复您的速度。


编辑:我看到一个更大的差异,这可能是您的 C# 不安全代码运行速度较慢的原因。

查看 this page about C# compared to C++ ,特别是:

“long 类型:在 C# 中,long 类型是 64 位,而在 C++ 中,它是 32 位。”

您应该将 C# 版本转换为使用 int,而不是 long。在 C# 中,long 是 64 位类型。这实际上可能会对您的指针操作产生深远的影响,因为我相信您在每次指针调用时无意中添加了 long->int 转换(带有溢出检查)。

此外,当您使用它时,您可能想尝试将整个函数包装在 unchecked block 中。 . C++ 不会执行您在 C# 中获得的溢出检查。

关于c# - 为什么我会看到使用 native 代码的速度提高了约 20%?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/883642/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com