2017-03-11 1 views
2

MSVC와 함께 아래의 사이 썬 코드를 컴파일 : Cython 코드에서 double 대신 float 리터럴을 사용 하시겠습니까?

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 형식으로 캐스팅 할 수 있다는 것을 알았습니다 : <float>1.0. 이것은 런타임 성능에 아무런 영향을 미치지 않습니까?

+0

Cython에서'1.0f'를 쓸 수없는 것 같습니다. '( 1-alpha)'시도해보십시오.그러면 생성 된 C 코드에서'(((float) 1) - alpha)'가 생성됩니다. 나는 MSVC가 그것에 관하여 경고 할 것인지 아닌지를 모른다. '1' 또는'1.0'을 사용 하느냐가 중요 할 수 있습니다. – zwol

+0

런타임 성능에 대해서는 중요하지 않지만, 100 % 확신하려면 생성 된 어셈블리 코드를 검사해야합니다. – zwol

답변

3

개정 문제는 (당신이 그것을 쓸 수 있다면 어떤 당신은 할 수 없습니다) 대신

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

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

을 쓰기에 대한 런타임 성능 저하가 있는지 여부입니다.

일반적으로에서이 유형의 질문에 대한 대답은 "물론 아닙니다. 컴파일러는 정확하게 동일한 기계 코드를 생성합니다 (최적화 도구를 켜 놓았는지 확인하십시오)"; 부동 소수점을 최적화하는 방법에 대한 명확하지 않은 제한이 있기 때문에 부동 소수점에 대해서는 항상 그렇지 않습니다. 이 경우에는 1.0이 정확히 float에 표시 될 수 있기 때문에 꽤 안전한 내기이지만, 알아내는 방법을 알려 드리겠습니다.

CPython의 통합 접착제 엄청난 양을 박리 한 후,이 사이 썬 상기 제 함수 생성하는 코드이다 : I 수동 1.0f 변경 (float)1.0이 함수의 두 번째 복사본을 생성

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

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

은 그리고 -O2 -march=native이 아닌을 사용하여 x86-64의 GCC 6.3을 사용하여 -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 

그래서 당신은 정확히 같은 어느 쪽이든 나오는 것을 볼 수있다 :이 (다시, 관련없는 잡담의 무리가 제거 된) 내가 가진 어셈블리 코드입니다. (신비한 숫자 10653532160x3f800000입니다. 1.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]); 
} 

을 적절 형식의 NumPy와 배열을 취 그 주위에 사이 썬 래퍼를 넣어. GCC는 이것을 자동 제어 할 수 있습니다. MSVC도 가능해야하며 Intel의 컴파일러는 확실히 할 수 있습니다. Cyber에서 커널을 작성하려고하지는 않을 것입니다. 아마도 autobctorizer를 활성화하기에 충분하게 주석을 달 수 없기 때문입니다. constrestrict은 필수적입니다.

관련 문제