【发布时间】:2017-05-05 17:27:16
【问题描述】:
我有一个嵌套的 for 循环来执行一些计算,并且数学已经在很大程度上简化了,但是我仍然有一个性能问题,我不确定我是否可以解决。由于这些 for 循环执行的次数太多,我不相信它可以解决。现在我不熟悉使用任何分析工具来帮助确定其中发生减速的位置,但我相当肯定这只是这些循环执行的次数。
如果能帮助我减少此代码并提高此代码的性能,我将不胜感激。我正在尝试远离 HPC 或高度并行化的解决方案,但如果这是使其真正有效的唯一方法,那么我会考虑走这条路。
这是 X= 20,000 和 N_zero= 45,420 的代码(从实际测试中提取的值):
Dictionary<decimal, int> n_alpha = new Dictionary<decimal, int>();
Random rand = new Random();
decimal r = 0m;
decimal check=0m;
for (int i = 0; i < X; i++)
{
B = N_0 = N_1 = N0_ = N1_ = 0;
for (int j = 0; j < N_zero; j++)
{
// need a random decimal value between 0 and 1
r = (decimal)rand.Next() / int.MaxValue;
if (r <= r1)
{
N0_ += 1;
N_0 += 1;
}
else if (r1 < r && r <= r2)
{
B += 1;
N0_ += 1;
N_1 += 1;
}
else if (r2 < r && r <= r3)
{
B += 1;
N_0 += 1;
N1_ += 1;
}
else if (r > r3)
{
N1_ += 1;
N_1 += 1;
}
}
check = N_0 * N_1 * N0_ * N1_;
if (check != 0)
{
decimal a = 1 - (B * N_zero) / ((N_0 *N1_) + (N0_ * N_1 ));
// technically only tracking 4 decimal points, so key should reflect this
decimal key = Math.Round(a, 4);
if (n_alpha.ContainsKey(key))
{
n_alpha[key] += 1;
}
else
{
n_alpha.Add(key, 1);
}
}
}
【问题讨论】:
-
如果不需要精度,您可以将小数类型更改为浮点数,并且您不介意一些舍入错误。
-
@Gilles
decimal无法避免舍入错误。它只是改变发生什么样的舍入错误。在这种情况下没有足够的上下文可以确定,但我同意在这种情况下使用decimal可能不合适(并且可能是导致性能不佳的一个相当重要的原因)。 -
这段代码中有很多可疑之处。与其详细指出所有这些,不如学习使用分析器。只有通过经验测量,才能始终如一地解决性能问题。设定一个目标,衡量绩效,将其与您的目标进行比较,找到最慢的事情,尝试修复它,然后重复直到完成。 互联网上的陌生人无法可靠地告诉您代码慢的地方。
-
也就是说,加速这段代码最明显的事情是使用双精度数,而不是小数。你能说说为什么你选择十进制而不是双精度吗?这些是财务计算吗?
-
顺便说一句,我使用双精度(或适当的整数)重新实现了这段代码,使用双精度的版本执行速度快了近 14 倍(它在大约 19 秒内完成,而几乎是 4 秒半给定代码的分钟数)。给定相同的随机种子,它也会产生相同的输出。
标签: c# performance for-loop