【问题标题】:Compare float array as int array将 float 数组与 int 数组进行比较
【发布时间】:2015-10-23 16:42:50
【问题描述】:

我需要对已排序数字数组进行优化的二进制搜索算法。我这样做了,发现使用浮点数存储数字比使用整数更快,因为最后我必须计算

(frameNumber-this->frameNumber[imin])/(this->frameNumber[imax]-this->frameNumber[imin])

this->frameNumber[imin] 是小于等于frameNumber 的最大帧数,this->frameNumber[imax] 是大于等于的最小帧数。该代码用于计算这两个关键帧之间的进度。 frameNumber 数组是静态的。我只需要排序一次。但是通过二分查找和上面的代码来多次访问它来计算进度。

从 int 到 float 的转换花费了一些周期。 然后我发现在asm中有很多fpu指令。我担心它们可能比整数慢。

所以问题来了。我可以将排序后的浮点数数组转换为 int* 并对其运行二进制搜索吗?

这意味着:

void binary_search(float key,float* array,...)
{
    int key_integer=*(int*)&key;
    int* array_intege(int*)array;
    binary_search_for_integers(key_integer,array_integer,...);
}

还是我上面的结论是错误的? (比如把int转换成float就不是那么费钱了,还是浮点之间的比较和整数一样快?

非常感谢!

【问题讨论】:

  • 你的问题不清楚,但直接的答案是不,你不能像这样转换数组。
  • 通常,这不起作用——它将每个元素的位解释为整数而不是浮点数。但是,IEEE 浮点有一个有趣的怪癖,即如果将其解释为相同长度的整数,它们会保持顺序。因此,如果您的系统上的 sizeof(int)==sizeof(float) 并且没有任何值是 NaN,则您的二进制搜索实际上可以工作。但 C 或 C++ 标准不保证这一点。
  • 它也不适用于负数。
  • 在我的机器上进行一些测试后,如果浮点数组中的值都是正数,它在 VS2012 中有效。负值将以相反的顺序排列(这是因为浮点数使用符号位而不是二进制补码)。编辑:看起来你打败了我。
  • int32_t 在 C 标准 C99 中是 32 位的,但未定义浮点大小,它只需要有一个最小范围。 en.wikipedia.org/wiki/C_data_types

标签: c++ c floating-point floating-point-conversion


【解决方案1】:

这似乎是个坏主意。正如@rlbond 指出的那样,对浮点数据使用整数比较实际上会产生一个正确排序的浮点数组。 (请参阅http://www.h-schmidt.net/FloatConverter/IEEE754.html 以使用浮点数的二进制表示。)在使用之前检查sizeof(int32_t) == sizeof(float)。

真的不需要像这样的 hack。 float 比较并不比 int 比较贵很多, 在现代硬件上。 (Intel Haswell:ucomiss 是 1 uop,每个周期吞吐量 1。与内存操作数相比是 2 uop,但没有微融合。它不能像 cmp/jcc 那样进行宏融合)但是,FP add/sub 和 FP mul 比它们的整数等效项具有更高的延迟,并且吞吐量更低。将整个数组转换为 float 似乎很愚蠢,因为您想在最后使用最小值和最大值进行一些 FP 数学运算。

load-and-convert-int-to-float 指令 (x86 cvtsi2ss (signed-integer 2 scalar single)) 与普通加载 (movss )。

如果您的数据最初是整数,并且您只使用其中的一部分,请使用int(避免转换为以后不再需要的值)。如果您确实访问了所有数据,并且只将您的数据用作浮点数,则将其存储为float。如果你同时使用它,最好将它存储为int,这样当你将它用作整数时它会更快,而当你将它用作浮点数时,速度几乎相同。

从您的代码示例中,您只是在使用最小值和最大值位置的值?在数组中查找最小值和最大值比对整个数组进行排序要快得多。 min/max 甚至使用压缩最小指令进行矢量化。

许多平台没有现代 Intel CPU 那样快的浮点,所以不要过度使用浮点。

【讨论】:

  • Nonono 不是最小值和最大值。我从link 修改了代码,imin 和 imax 只是两个迭代器。 'this->frameNumber[imin]' 是小于等于 'frameNumber' 的最大 frameNumber,而 'this->frameNumber[imax]' 是大于等于的最小 frameNumber。该代码用于计算这两个关键帧之间的进度。所以我只会把它全部用作花车。该数据是静态的。我只需要在从硬盘加载它时对其进行排序和转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-14
  • 1970-01-01
  • 2017-09-10
  • 2015-04-27
  • 1970-01-01
  • 2017-12-22
相关资源
最近更新 更多