在Cython代码中使用float文字而不是double?

时间:2017-03-11 15:29:05

标签: python cython

使用MSVC编译下面的Cython代码时:

cpdef float interpolate(float start, float end, float alpha):
    return end * alpha + start * (1.0 - alpha)

我收到了这个警告:

warning C4244: '=': conversion from 'double' to 'float', possible loss of data

它与代码中的1.0相关,应该是浮点数,但它是双倍的。可以修改上面的Cython代码以防止出现警告吗?

编辑:刚刚发现我可以将此文字转换为浮动状态:<float>1.0。这无论如何会影响运行时性能吗?

1 个答案:

答案 0 :(得分:3)

修订后的问题是写作是否存在任何运行时性能损失

cpdef float interpolate_cast(float start, float end, float alpha):
    return end * alpha + start * (<float>1.0 - alpha)

而不是

cpdef float interpolate_lit(float start, float end, float alpha):
    return end * alpha + start * (1.0f - alpha)

(如果你能写出来,那你不能)。

一般来说,对这类问题的回答是“当然不是,编译器会以任何一种方式生成完全相同的机器代码(确保你确实打开了优化器)”;但对于浮点而言并非总是如此,因为对浮点的优化方式有非明显的限制。在这种情况下,这是一个非常安全的赌注,因为1.0float中完全可以表示,但是让我告诉你如何确定。

在剥离了大量的CPython集成胶之后,这是Cython为上面的第一个函数生成的代码:

float interpolate_cast(float start, float end, float alpha) {
  float r;

  r = ((end * alpha) + (start * (((float)1.0) - alpha)));
  goto L0;
  L0:;
  return r;
}

我手动创建了此函数的第二个副本,(float)1.0已更改为1.0f,并使用-O2 -march=native而不是使用-ffast-math。这是我得到的汇编代码(再次,删除了一堆无关的聊天):

interpolate_cast:
        vmovss  .LC0(%rip), %xmm3
        vsubss  %xmm2, %xmm3, %xmm3
        vmulss  %xmm0, %xmm3, %xmm0
        vfmadd231ss     %xmm2, %xmm1, %xmm0
        ret

interpolate_lit:
        vmovss  .LC0(%rip), %xmm3
        vsubss  %xmm2, %xmm3, %xmm3
        vmulss  %xmm0, %xmm3, %xmm0
        vfmadd231ss     %xmm2, %xmm1, %xmm0
        ret

.LC0:
        .long   1065353216

所以你可以看到两种方式完全相同。 (神秘的数字10653532160x3f8000001.0f。)您可以使用MSVC重复此实验,以确定该编译器是否执行相同的操作;我期待它。

如果此功能对性能至关重要,那么您应该考虑将其设置为矢量化。例如,你可以编写这个C计算内核:

#include <stddef.h>
void interpolate_many(float *restrict dest,
                      float const *restrict start,
                      float const *restrict end,
                      float const *restrict alpha,
                      size_t n)
{
  for (size_t i = 0; i < n; i++)
    dest[i] = end[i] * alpha[i] + start[i] * (1.0f - alpha[i]);
}

并在其周围放置一个Cython包装器,它采用适当类型的NumPy数组。海湾合作委员会可以对此进行自动审核; MSVC也应该能够,而英特尔的编译器当然可以。我不会尝试在Cython中编写内核,因为您可能无法对其进行充分注释以激活自动向量器;那些constrestrict是必不可少的。