libsimdpp медленнее, чем отладка gcc - PullRequest
0 голосов
/ 01 марта 2019

Мне нужна была кросс-платформенная инструкция SIMD между arm и x86.Поэтому я нашел библиотеку с именем libsimdpp и запустил этот пример .

Я немного изменил его, чтобы сравнить его со стандартным подходом cpp для добавления двух массивов, но пример libSimd всегда работал хуже.

Результаты

  • 23Миллисекунды - libSimd
  • 1 Миллисекунды - обычное добавление в cpp

Это что-то не так с тем, как я использую библиотеку или как она построена.

Изменения, которые я внес в пример.

https://pastebin.com/L14DCrky

#define SIMDPP_ARCH_X86_SSE4_1 true
#include <simdpp/simd.h>
#include <iostream>
#include <chrono>
//example where i got this from
//https://github.com/p12tic/libsimdpp/tree/2e5c0464a8069310d7eb3048e1afa0e96e08f344

// Initializes vector to store values
void init_vector(float* a, float* b, size_t size) {
    for (int i=0; i<size; i++) {
        a[i] = i * 1.0;
        b[i] = (size * 1.0) - i - 1;
    }
}



using namespace simdpp;
int main() {
    //1048576
    const unsigned long SIZE = 4 * 150000;

    float vec_a[SIZE];
    float vec_b[SIZE];
    float result[SIZE];

    ///////////////////////////*/
    //LibSIMDpp
    //*
    auto t1 = std::chrono::high_resolution_clock::now();

    init_vector(vec_a, vec_b, SIZE);
    for (int i=0; i<SIZE; i+=4) {
        float32<4> xmmA = load(vec_a + i);  //loads 4 floats into xmmA
        float32<4> xmmB = load(vec_b + i);  //loads 4 floats into xmmB
        float32<4> xmmC = add(xmmA, xmmB);  //Vector add of xmmA and xmmB
        store(result + i, xmmC);            //Store result into the vector
    }

    auto t2 = std::chrono::high_resolution_clock::now();

    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()
              << " milliseconds\n";
    //*/


    ///////////////////////////*/
    //standard
    //*
    init_vector(vec_a, vec_b, SIZE);
    t1 = std::chrono::high_resolution_clock::now();

    for (auto i = 0; i < SIZE; i++) {
        result[i] = vec_a[i]  + vec_b[i];
    }

    t2 = std::chrono::high_resolution_clock::now();

    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()
              << " milliseconds\n";
    //*/


    int i = 0;
    return 0;
}

1 Ответ

0 голосов
/ 02 марта 2019

Обычно отладочная сборка замедляет векторизованный вручную код больше, чем скалярную, даже если вы непосредственно используете _mm_add_ps встроенные функции.(Обычно потому, что вы склонны использовать больше отдельных операторов, а debug code-gen компилирует каждый оператор отдельно.)

Вы используете библиотеку обертки C ++, поэтому в режиме отладки это существенный дополнительный слой материала, который не будет оптимизировать, потому что вы сказали компилятору не делать этого.Так что не удивительно, что он так сильно тормозит, что это хуже, чем скаляр.См. Почему этот класс-обёртка C ++ не вставлен? * Например, 1007 *.(Даже __attribute__((always_inline)) не сильно влияет на производительность; передача аргументов по-прежнему приводит к перезагрузке / сохранению для создания другой копии).

Не тестируйте отладочные сборки, это бесполезно и говорит вам очень немного о -O3 производительности. (Вы также можете использовать -O3 -march=native -ffast-math, в зависимости от вашего варианта использования.)

...