проблема производительности сборки неоновых рук в xiaomi5s

arm neon

143 просмотра

2 ответа

Рассмотрим следующие коды: Первый фрагмент кода:

void run_new(const float* src, float* dst,
        size_t IH, size_t IW, size_t OH, size_t OW,
        size_t N) {
    rep(n, N) {
        const float* src_ptr = src + IW * IH * n;
        float* outptr = dst;

        const float* r0 = src_ptr;
        const float* r1 = src_ptr + IW;

        float32x4_t k0123 = vdupq_n_f32(3.f);
        rep(h, OH) {
            size_t width = OW >> 2;

            asm volatile(
                    "dup v21.4s, %4.s[0] \n"
                    "dup v22.4s, %4.s[1] \n"
                    "dup v23.4s, %4.s[2] \n"
                    "dup v24.4s, %4.s[3] \n"
                    "mov x3, xzr \n"
                    "0:           \n"
                    "ldr q0, [%1] \n"
                    "ld1 {v1.4s, v2.4s}, [%2], #32 \n"

                    "add x3, x3, #0x1 \n"
                    "cmp %0, x3 \n"

                    "ld1 {v3.4s, v4.4s}, [%3], #32 \n"
                    "fmla v0.4s, v1.4s, v21.4s \n"  // src[i] * k[i]
                    "fmla v0.4s, v2.4s, v22.4s \n"

                    "fmla v0.4s, v3.4s, v23.4s \n"
                    "fmla v0.4s, v4.4s, v24.4s \n"

                    "str q0, [%1], #16 \n"
                    "bne 0b \n"
                    : "+r"(width), "+r"(outptr), "+r"(r0), "+r"(r1)
                    : "w"(k0123)
                          : "cc", "memory", "x3", "v0", "v1", "v2", "v3", "v4", "v21", "v22", "v23", "v24");
        }

    }
}

Второй фрагмент кода:

 void run_origin(const float* src, float* dst,
        size_t IH, size_t IW, size_t OH, size_t OW,
        size_t N) {

    rep(n, N) {
        const float* src_ptr = src + IW * IH * n;
        float* outptr = dst;

        const float* r0 = src_ptr;
        const float* r1 = src_ptr + IW;

        float32x4_t k0123 = vdupq_n_f32(3.f);
        rep(h, OH) {
            size_t width = OW >> 2;

            asm volatile(
                    "dup v21.4s, %4.s[0] \n"
                    "dup v22.4s, %4.s[1] \n"
                    "dup v23.4s, %4.s[2] \n"
                    "dup v24.4s, %4.s[3] \n"
                    "mov x3, xzr \n"
                    "mov x4, xzr \n"
                    "0:           \n"
                    "add x19, %2, x4 \n"
                    "ldr q0, [%1] \n"  // load dst 0, 1, 2, 3
                    "ld1 {v1.4s, v2.4s}, [x19]\n"  // 1, 2, 4, 6

                    "add x3, x3, #0x1 \n"
                    "cmp %0, x3 \n"

                    "add x19, %3, x4 \n"
                    "ld1 {v3.4s, v4.4s}, [x19]\n"
                    "fmla v0.4s, v1.4s, v21.4s \n"  // src[i] * k[i]
                    "fmla v0.4s, v2.4s, v22.4s \n"

                    "fmla v0.4s, v3.4s, v23.4s \n"
                    "fmla v0.4s, v4.4s, v24.4s \n"

                    "add x4, x4, #0x20 \n"
                    "str q0, [%1], #16 \n"
                    "bne 0b \n"
                    "add %2, %2, x4 \n"
                    "add %3, %3, x4 \n"
                    : "+r"(width), "+r"(outptr), "+r"(r0), "+r"(r1)
                    : "w"(k0123)
                          : "cc", "memory", "x3", "x4", "x19", "v0", "v1", "v2", "v3", "v4", "v21", "v22", "v23", "v24");

        }

    }
}

Весь код в тесте производительности рука неоновой сборки

Я тестирования производительности этих двух кодов на xiaomi5s, xiaomi6, redmi, Фрагмент производительности:

N: 12 IH: 224 IW: 224 OH: 112 OW: 112

  1. Происхождение: 325,35058 мфлопс --- новый: 4275,63483 мфлопс --- ускорение: 13,14162 xiaomi5s
  2. Происхождение: 3082.00078 мфлопс --- новый: 3063.45047 мфлопс --- ускорение: 0.99398 xiaomi6
  3. Происхождение: 1761.05058 мфлопс --- новое: 1814.37185 мфлопс --- ускорение: 1.03028 редми

Следующий тест в xiaomi5s.

N: 12 IH: 48-256 IW: 224

  1. N: 12 IH: 48 IW: 224 OH: 24 OW: 112 источник прохождения: 3721,16633 мфлопс --- новый: 4935,31729 мфлопс --- ускорение: 1,3262
  2. N: 12 IH: 80 IW: 224 OH: 40 OW: 112 источник прохождения: 1185,58378 мфлопс --- новый: 3852,38266 мфлопс --- ускорение: 3,24936
  3. N: 12 IH: 112 IW: 224 OH: 56 OW: 112 источник прохождения: 1021,83468 мфлопс --- новый: 3503,70672 мфлопс --- ускорение: 3,42884
  4. N: 12 IH: 144 IW: 224 OH: 72 OW: 112 происхождение: 797.61461 мфлопс --- новый: 4167.12780 мфлопс --- ускорение: 5.22449
  5. N: 12 IH: 176 IW: 224 OH: 88 OW: 112 источник прохождения: 465,55073 мфлопс --- новый: 4084,54206 мфлопс --- ускорение: 8,77357
  6. N: 12 IH: 208 IW: 224 OH: 104 OW: 112 источник прохождения: 373,99237 мфлопс --- новый: 4255,78687 мфлопс --- ускорение: 11,37934
  7. N: 12 IH: 240 IW: 224 OH: 120 OW: 112 Происхождение происхождения: 341,57406 мфлопс --- новый: 4290,58840 мфлопс --- ускорение: 12,56122

N: 12 IH: 224 IW: 48-256

  1. N: 12 IH: 224 IW: 48 OH: 112 OW: 24 происхождение: 3660,35916 мфлопс --- новый: 4729,61877 мфлопс --- ускорение: 1,29212
  2. N: 12 IH: 224 IW: 80 OH: 112 OW: 40 perf происхождение: 2918.48755 мфлопс --- новый: 4748.17285 мфлопс --- ускорение: 1.62693
  3. N: 12 IH: 224 IW: 112 OH: 112 OW: 56 пер. Происхождения: 951,03852 мфлопс --- новый: 4051,84318 мфлопс --- ускорение: 4,26044
  4. N: 12 IH: 224 IW: 144 OH: 112 OW: 72 пер. Происхождения: 1186,74405 мфлопс --- новый: 4160,18572 мфлопс --- ускорение: 3,50555
  5. N: 12 IH: 224 IW: 176 OH: 112 OW: 88 пер. Происхождения: 533,47286 мфлопс --- новый: 4199,36622 мфлопс --- ускорение: 7,87175
  6. N: 12 IH: 224 IW: 208 OH: 112 OW: 104 Perf источник: 447,30682 мфлопс --- новый: 4092,22256 мфлопс --- ускорение: 9,14858
  7. N: 12 IH: 224 IW: 240 OH: 112 OW: 120 PER Происхождение: 442,58206 мфлопс --- новый: 4200,13672 мфлопс --- ускорение: 9,49007

IC: 2-12 IH: 224 IW: 224

  1. N: 2 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 3794,45684 мфлопс --- новый: 5236,48508 мфлопс --- ускорение: 1,38004
  2. N: 3 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 3790,20521 мфлопс --- новый: 5150,30622 мфлопс --- ускорение: 1,35885
  3. N: 4 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 2117,55521 мфлопс --- новый: 4329,34274 мфлопс --- ускорение: 2,04450
  4. N: 5 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 1290,43541 мфлопс --- новый: 3915,65607 мфлопс --- ускорение: 3,03437
  5. N: 6 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 1038.86926 мфлопс --- новый: 3747.69392 мфлопс --- ускорение: 3.60747
  6. N: 7 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 845,26878 мфлопс --- новый: 4025,81237 мфлопс --- ускорение: 4,76276
  7. N: 8 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 658,23150 мфлопс --- новый: 3971,62335 мфлопс --- ускорение: 6,03378
  8. N: 9 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 527,99489 мфлопс --- новый: 4163,94501 мфлопс --- ускорение: 7,88634
  9. N: 10 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 416,75353 мфлопс --- новый: 4119,03296 мфлопс --- ускорение: 9,88362
  10. N: 11 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 378,38875 мфлопс --- новый: 4203,33717 мфлопс --- ускорение: 11.10852
  11. N: 12 IH: 224 IW: 224 OH: 112 OW: 112 источник прохождения: 350,36924 мфлопс --- новый: 4202,19842 мфлопс --- ускорение: 11,99363

Я запутался в тесте производительности xiaomi5s, Почему производительность первого кода на xiaomi5s так плоха.

Я предполагаю, что это может быть вызвано нарушением конвейера неона, если он ожидает нормального регистра, такого как ld1 {v3.4s, v4.4s}, [x19]ожидание, x19которое вычисляется с помощью add x19, %3, x4, но я не очень уверен。

Детали дополнения:

  1. процессор xiaomi5s: Qualcomm Snapdragon 821
  2. процессор xiaomi6: Qualcomm Snapdragon 835
  3. Redmi процессор: MediaTek Helio X20

Компиляция (версия лязга: 5.0.0) вариант: clang++ -std=c++11 -Ofast.


  1. Я изменяю ldr q0, [%2]на ld1 v0.4s, [%2], но результат тот же, производительность run_originможет быть немного быстрее, около 1% -3%.

N: 12 IH: 224 IW: 224 OH: 112 OW: 112

Происхождение: 342,96631 мфлопс. --- asm: 4288.51646 мфлопс. --- ускорение: 12.50419

  1. Я изменяю fmla v0.4s, v1.4s, v21.4sна smlsl2 v0.2d, v1.4s, v21.4s, но результат тот же.

    N: 12 IH: 224 IW: 224 OH: 112 OW: 112

Происхождение: 348.03699 мфлопс --- Асм .: 4245.18804 мфлопс --- ускорение: 12.19752

  1. Я изменяю fmla v0.4s, v1.4s, v21.4sна fadd v0.4s, v1.4s, v21.4s, исходный код становится быстрее.

N: 12 IH: 224 IW: 224 OH: 112 OW: 112

Происхождение: 743,95433 мфлопс. --- asm: 4756,65769 мфлопс. --- ускорение: 6,39375

Автор: Sethbrin Источник Размещён: 03.10.2019 02:51

Ответы (2)


0 плюса

Неожиданное предположение состоит в том, что узкое место в подсистеме памяти и кэша столь же вероятно, как и ядро. Возможно, в первом случае происходит что-то, что запрещает автоматическую предварительную загрузку (или у xiaomi5s этого нет или он отключен)?

Возможно, было бы интересно добавить pld(или, скорее, prfm) инструкцию, хотя я никогда не находил, чтобы они сильно помогали на Cortex-A9, по крайней мере.

Простой способ проверить, fmlaявляется ли узкое место, состоит в том, чтобы закомментировать некоторые или все инструкции по обработке данных (конечно, результат будет неправильным!)

Автор: NickJH Размещён: 16.10.2017 10:07

-1 плюса

Я до сих пор не так хорошо знаком с NEON64, как с NEON32, но есть несколько вещей, которые я бы не делал в вашем коде:

  • Почему вы используете инструкцию VFP "ldr"? Переключение между VFP и NEON может стоить много циклов, особенно если эти инструкции обращаются к памяти. То, что оба разделяют регистры, не означает, что они являются одной и той же единицей. Измените его на LD1 ...... 4s

  • Вы хотите это 32-битный или 64-битный? Выберите x3 или w3 и придерживайтесь его.

  • Вы уверены, что хотите объединить умножение с fmla? Может быть, да, а может, и нет, но учтите, что умноженные слияния стоят больше

ура

Автор: Jake 'Alquimista' LEE Размещён: 14.10.2017 11:31
Вопросы из категории :
32x32