Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
535 views
in Technique[技术] by (71.8m points)

optimization - Define a `static const` SIMD Variable within a `C` Function

I have a function in this form (From Fastest Implementation of Exponential Function Using SSE):

__m128 FastExpSse(__m128 x)
{
    static __m128  const a   = _mm_set1_ps(12102203.2f); // (1 << 23) / ln(2)
    static __m128i const b   = _mm_set1_epi32(127 * (1 << 23) - 486411);
    static __m128  const m87 = _mm_set1_ps(-87);
    // fast exponential function, x should be in [-87, 87]
    __m128 mask = _mm_cmpge_ps(x, m87);

    __m128i tmp = _mm_add_epi32(_mm_cvtps_epi32(_mm_mul_ps(a, x)), b);
    return _mm_and_ps(_mm_castsi128_ps(tmp), mask);
}

I want to make it C compatible.
Yet the compiler doesn't accept the form static __m128i const b = _mm_set1_epi32(127 * (1 << 23) - 486411); when I use C compiler.

Yet I don't want the first 3 values to be recalculated in each function call.
One solution is to inline it (But sometimes the compilers reject that).

Is there a C style to achieve it in case the function isn't inlined?

Thank You.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Remove static and const.

Also remove them from the C++ version. const is OK, but static is horrible, introducing guard variables that are checked every time, and a very expensive initialization the first time.

__m128 a = _mm_set1_ps(12102203.2f); is not a function call, it's just a way to express a vector constant. No time can be saved by "doing it only once" - it normally happens zero times, with the constant vector being prepared in the data segment of the program and simply being loaded at runtime, without the junk around it that static introduces.

Check the asm to be sure, without static this is what happens: (from godbolt)

FastExpSse(float __vector(4)):
        movaps  xmm1, XMMWORD PTR .LC0[rip]
        cmpleps xmm1, xmm0
        mulps   xmm0, XMMWORD PTR .LC1[rip]
        cvtps2dq        xmm0, xmm0
        paddd   xmm0, XMMWORD PTR .LC2[rip]
        andps   xmm0, xmm1
        ret
.LC0:
        .long   3266183168
        .long   3266183168
        .long   3266183168
        .long   3266183168
.LC1:
        .long   1262004795
        .long   1262004795
        .long   1262004795
        .long   1262004795
.LC2:
        .long   1064866805
        .long   1064866805
        .long   1064866805
        .long   1064866805

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...