【问题标题】:How to make this color percentage function faster? C++如何让这个颜色百分比函数更快? C++
【发布时间】:2015-06-17 13:55:57
【问题描述】:
extern inline double getColorPercentage(uint8_t *pixel, uint8_t *pixel2) {
    //pixel 1 is 255, 255, 255
    //pixel 2 is 0, 0, 0
    //match is 0

    //pixel 1 and 2 is 255, 255, 255
    //match is 1.0
    return (255-fabs(pixel[2] - pixel2[2])) * (255-fabs(pixel[1] - pixel2[1])) * (255-fabs(pixel[0] - pixel2[0])) /16581375.0;
}

我编写了这个函数并尝试对其进行优化,并希望它可以进一步优化。我经常使用它,有人知道提高性能的方法吗?

【问题讨论】:

  • 你为什么用fabs()而不是abs()
  • 您应该使用static inline 而不是extern inline
  • 我认为这应该迁移到代码审查。该网站不是菜单上的选项之一(我想知道为什么?),我不想将其标记为“需要主持人干预”。也许其他用户可以迁移它?
  • @Panzercrisis 最好的做法是投票关闭“太宽泛”并发表评论。它不在列表中,因为 a) 它还没有完全毕业(但计划这样做)b) 仍然有相当多的 SO 用户没有了解 Code Review 的真正主题。跨度>
  • pixel1pixel2 应声明为 const uint8_t *

标签: c++ math optimization


【解决方案1】:

您有很多不必要的 intfloat 转换正在进行。除以常数也可以转换为乘法。这是一个可能更高效的版本:

inline double getColorPercentage(const uint8_t *pixel, const uint8_t *pixel2)
{
    const double scale = 1.0 / (255.0 * 255.0 * 255.0); // compile-time constant
    int m0 = 255 - abs(pixel[0] - pixel2[0]); // NB: use std::abs rather than fabs
    int m1 = 255 - abs(pixel[1] - pixel2[1]); // and keep all of this part
    int m2 = 255 - abs(pixel[2] - pixel2[2]); // in the integer domain
    int m = m0 * m1 * m2;
    return (double)m * scale;
}

与往常一样,您应该仔细地对原始版本和任何优化版本进行基准测试和分析,并注意使用一种编译器和目标平台进行的优化可能对另一种没有用处。

【讨论】:

  • 是我的想象还是你们的函数调用次数一样?
  • 表面上是的,但abs 应该被内联。
  • 为什么fabs 不是?特别是,就像整数一样,it's usually as simple as setting the value of a single bit.
  • 临时变量只是为了清晰/可读性和易于调试而存在 - 它们将被编译器优化掉,因此它们不会对性能产生影响。
  • @Panzercrisis:为了清楚起见。如果配置正确,编译器会将所有这些混合到一个汇编代码中,并且不使用任何基于本地堆栈的临时变量。
【解决方案2】:

首先我建议您使用std::abs() 而不是std::fabs(),因为您正在处理不是浮点类型的uint8_t。如果这仍然不能给你足够的性能,你可以试试这个:

extern inline double getColorPercentage(uint8_t *pixel1, uint8_t *pixel2)
{
    int a = 255 - (pixel1[2] > pixel2[2] ? pixel1[2] - pixel2[2] : pixel2[2] - pixel1[2]);
    int b = 255 - (pixel1[1] > pixel2[1] ? pixel1[1] - pixel2[1] : pixel2[1] - pixel1[1]);
    int c = 255 - (pixel1[0] > pixel2[0] ? pixel1[0] - pixel2[0] : pixel2[0] - pixel1[0]);
    return (a * b * c) / 16581375.0;
}

与往常一样,请确保您在发布版本上和版本中使用优化进行编译。

【讨论】:

  • @LightnessRacesinOrbit 一点点 aixelsyd ;)
  • 这个看起来不错,但编译器会更难摆脱测试。如果基准测试证明它在随机数据上比简单的fabs() 版本慢得多,我不会感到惊讶。
【解决方案3】:

除了其他答案之外,您可能还想检查您的计算是否已矢量化。请看this my answer;我什至可以想象,对于您的情况,可以有一个单独的内在函数。

事实上,在你的特定函数中,减法/乘法“循环”可以被矢量化,但是如果你从某个循环中调用你的函数(我假设你这样做了,否则为什么它是一个瓶颈?),那么也许矢量化外循环将证明效率更高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多