1

我有一个非常复杂和复杂的数据拟合程序,它使用 Levenverg-Marquardt 算法进行双精度拟合(基本上拟合类是模板化的,但我使用实例化它来加倍)。拟合过程包括:

  • 计算误差函数(卡方)
  • 求解线性方程组(我使用 lapack)
  • 计算函数相对于参数的导数,我想拟合数据(通常是 20 多个参数)
  • 连续计算函数值:函数是正弦函数和指数函数的复杂组合,具有少量谐波。

我的一位同事建议我使用整数至少快 10 倍。我的问题是:

  1. 我会得到那种改善是真的吗?
  2. 将所有内容转换为整数是否安全?这有什么缺点?
  3. 对于整个问题,您有什么建议?你会怎么做?

该程序是为在线计算信号中的一些参数而开发的,这意味着程序必须尽可能快,但我想知道是否值得启动将所有内容转换为整数的项目。

4

4 回答 4

6

改进的程度取决于您的平台。例如,如果您的平台有一个快速浮点协处理器,那么在浮点中执行算术可能比积分算术更快。

您可以通过优化算法而不是切换到整数算术来获得更多的性能增益。

提高性能的另一种方法是减少数据缓存命中并减少分支和循环。

我会测量程序的性能以找出瓶颈所在,然后查看大部分性能发生的部分。例如,在我的嵌入式系统中,像您建议的那样的微优化节省了 3 微秒。这种收益不值得重新测试整个系统。如果它有效,请不要修复它。首先关注正确性和稳健性。

于 2013-10-10T15:39:16.170 回答
2

这里的底线是您必须对其进行测试并自己决定。使用真实数据分析发布版本。

1-我会得到那种改善是真的吗?

可能是,可能不是。这取决于许多因素,例如

  1. double从 转换为需要多长时间int
  2. 你的机器上有多大的单词
  3. 您正在使用什么平台/工具集以及您启用了哪些优化
  4. (也许)你的平台上有多大的缓存行
  5. 你的记忆有多快
  6. 您的平台计算浮点数与整数的速度。

谁知道还有什么。简而言之,任何人都无法确定您是否会提高性能的复杂变量太多。

但我会高度怀疑你朋友的说法,“至少快 10 倍”。

2-将所有内容转换为整数是否安全?这有什么缺点?

这取决于您要转换什么以及如何转换。显然,将值转换为123.456整数是绝对不安全的。

缺点包括精度损失、准确性损失以及实际进行转换的空间和时间方面的费用。另一个显着的缺点是您必须编写大量代码,并且您编写的每一行代码都可能是新错误的来源。

3-您对整个问题有什么建议?你会怎么做?

我会退后一步,深呼吸。在真实条件下分析您的代码。确定瓶颈的来源。找出真正的问题是什么,如果有的话。

识别算法中的低效之处,并修复它们。

把硬件扔到问题上。

然后你可以努力开始微优化。这将是我最后的手段,特别是如果您正在考虑的优化技术需要编写大量代码。

于 2013-10-10T15:42:48.797 回答
2

首先,这似乎是在尝试进行不必要的优化。

其次,doubles至少是 64 位。 ints在大多数系统上都是 32 位的。所以你有几个选择:截断双精度(这会将你的精度降低到单精度),或者将其存储在 2 个整数的空间中,或者将其存储为一个unsigned long long(至少也是 64 位)。对于前两个选项,您将面临性能损失,因为您必须在您正在操作的双精度数和您将其存储为的整数之间来回转换数字。对于第三个选项,您不会获得任何性能提升(就内存使用而言),因为它们的大小基本相同 - 所以您只是无缘无故地将它们转换为整数。

因此,要解决您的问题:

1) 值得怀疑,但您可以尝试自己查看。

2)问题不在于存储,因为这些位在进入内存时只是位。问题是算术。由于您声明需要双精度,因此尝试对整数类型执行这些操作不会给您所需的结果。

3) 在证明某些东西需要提高性能之前不要进行优化。永远记住阿姆达尔定律:使常见情况快速,罕见情况正确。

于 2013-10-10T15:39:22.853 回答
0

我会做的是:

首先在单线程模式下调整它(通过随机暂停方法),直到找不到任何减少周期的方法。我发现的东西有:

  • 大部分时间花在库函数上,如sin, cos, exp, 以及log参数通常不变的地方,所以答案是一样的。解决方案称为“记忆”,您可以在其中找到存储参数和结果的旧值的位置,并在调用函数之前先检查那里。

  • 在调用诸如 DGEMM(lapack 矩阵乘法)之类的库函数时,人们会假设这些函数已针对牙齿进行了优化,它们实际上花费了大量时间调用函数来确定矩阵是上三角形还是下三角形、正方形、对称或无论如何,而不是实际做乘法。如果是这样,答案很明显 - 为您的情况编写一个特殊的例程。

不要说“但我没有这些问题”。当然——你可能有不同的问题——但找到它们的过程是一样的。

一旦你在单线程中让它尽可能快,然后弄清楚如何并行化它。多线程可能有很高的开销,所以最好不要紧耦合线程。

关于您关于从双精度数转换为整数的问题,其他答案是正确的。它只在非常特殊的情况下才有意义。

于 2013-10-10T16:40:59.803 回答