【问题标题】:optimization of functions with many input parameters in CC中具有许多输入参数的函数的优化
【发布时间】:2016-12-02 01:33:49
【问题描述】:

我的代码中有一个大循环内的函数,它占用了大部分 cpu 时间:

inline void myfunc(double v1, ... , double vN){
  ...
  (general, complex, multiline manipulation of v1 .. vN)
  ...
  res = v1;
}

其中res是一个全局变量,传递参数的数量N约为20。我尝试通过传递变量指针来优化函数调用:

inline void myfunc(double *v1, ... , double *vN){
  ...
  (general, complex, multiline manipulation of *v1 .. *vN)
  ...
  res = *v1;
}

然后当然是通过myfunc(&v1, ..., &vN) 调用它。我假设在第一种情况下,函数必须在每次调用时创建本地 v1..vN 变量,而在第二种情况下则不需要。 我发现这两个版本都有效(呃!)但实际上我在第二种情况下根本没有加速。这是为什么呢?

【问题讨论】:

  • 除了传递 20 个参数,你能传递一个指向包含参数的结构的指针吗?
  • 通过获取地址,您更有可能阻止编译器进行优化。
  • 你的参数都是double吗?
  • @cipper 如果编译器可以将您表达的意图优化为具有相同结果的更简单代码,则编译器没有义务实际传递任何参数。您表达的意图越简单,优化器的工作就越容易(假设您已启用它)。 Google 假设规则。
  • 如果您的代码是 C,则不要包含 C++ 标签;如果您的代码是 C++,请不要包含 C 标记。这些语言有一些共同点,但现代 C++ 程序与现代 C 程序完全不同,反之亦然。

标签: c performance optimization parameter-passing


【解决方案1】:

您不是将double 作为参数复制到函数中,而是复制一个指针。

如果您在 x64(每个8 bytes)架构上,则指针是 size_tdouble 完全相同。

不止于此:

  • 现在您需要取消引用传递的参数。
  • 在将它们传递给方法之前,您需要获取指向它们的指针
  • 您在计算本身中失去了可能的编译器优化,这可能比传递的参数更昂贵。

如果此方法包含需要很长时间的操作,则优化操作本身而不是传递参数。

您没有提供足够的信息来帮助您优化函数体本身,但知道对于繁重的向量计算,您可能希望使用多线程处理 - 甚至可能在 GPU 上。

【讨论】:

    【解决方案2】:

    想想你在做什么:

    • myfunc 的第一个版本中,您将按值传递Ndouble 参数,制作sizeof(double)N 个副本。

    • 在第二个版本中,您通过值传递 N double* 参数,然后访问它们。您正在制作sizeof(double*)N 个副本,然后遵循指针间接。传递指针/引用还会阻止编译器执行更积极的优化。

    简而言之,第二个版本比第一个版本做得更多。如果您没有发现任何差异,则编译器很可能能够优化间接/复制。

    您可以使用很棒的 gcc.godbolt.org 网站在多个编译器上轻松比较两个版本的生成程序集。

    【讨论】:

    • 谢谢!现在我看到了。有什么办法可以加快通话速度?
    • @cipper:您是否尝试过将值存储在数组中并将指针传递给数组? (不相关) - 您是否考虑过计算的并行性?
    • 如上所述,我实际上传递了不同类型的非常不同的变量,这里在 v1..vN 中进行了简化。但我会考虑的。谢谢你。代码已经 openmp 并行了。
    • @cipper:啊,对不起。如何将变量存储在std::tuple (或class/struct 中并传递对它的引用?它将避免复制每个元素。
    • 我想将此代码保留在纯 C 中......但是我会记住这个建议。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2018-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 2014-03-24
    相关资源
    最近更新 更多