Вот этот код:
#include 
#include 

#define VECTOR_SIZE 16
#define CHANNELS_PER_PIXEL 3
#define MAX_ORDER 4

void swap_line(const float *src, float *dst, unsigned n,
               const int order[MAX_ORDER], float extra) {
    unsigned i, j, k;
    const unsigned CHANNEL_COUNT = (order[3] != -1) ? MAX_ORDER : 3;
    __m512 r_v, g_v, b_v, extra_v;
    __m512 outputs[MAX_ORDER];
    __m512i idx_r_v, idx_g_v, idx_b_v;
    __m512 zero_v = _mm512_setzero_ps();
    __mmask16 mask;

    extra_v = _mm512_set1_ps(extra);

    for (i = 0; i < n; i += VECTOR_SIZE) {
        unsigned len = (n - i >= VECTOR_SIZE) ? VECTOR_SIZE : n - i;

        int32_t idx[VECTOR_SIZE];
        for (j = 0; j < len; ++j) {
            idx[j] = (i + j) * CHANNELS_PER_PIXEL;
        }
        for (; j < VECTOR_SIZE; ++j) {
            idx[j] = 0;
        }

        idx_r_v = _mm512_loadu_si512(idx);
        idx_g_v = _mm512_add_epi32(idx_r_v, _mm512_set1_epi32(1));
        idx_b_v = _mm512_add_epi32(idx_r_v, _mm512_set1_epi32(2));

        mask = (1U << len) - 1;

        r_v = _mm512_mask_i32gather_ps(zero_v, mask, idx_r_v, (const void *)src,
                                       4);
        g_v = _mm512_mask_i32gather_ps(zero_v, mask, idx_g_v, (const void *)src,
                                       4);
        b_v = _mm512_mask_i32gather_ps(zero_v, mask, idx_b_v, (const void *)src,
                                       4);

        for (k = 0; k < CHANNEL_COUNT; ++k) {
            switch (order[k]) {
            case 0:
                outputs[k] = r_v;
                break;
            case 1:
                outputs[k] = g_v;
                break;
            case 2:
                outputs[k] = b_v;
                break;
            case 3:
                outputs[k] = extra_v;
                break;
            }
        }

        __m512i dst_idx_v;
        for (j = 0; j < CHANNEL_COUNT; ++j) {
            int32_t dst_idx[VECTOR_SIZE];
            for (k = 0; k < len; ++k) {
                dst_idx[k] = (i + k) * CHANNEL_COUNT + j;
            }
            for (; k < VECTOR_SIZE; ++k) {
                dst_idx[k] = 0;
            }
            dst_idx_v = _mm512_loadu_si512(dst_idx);

            _mm512_mask_i32scatter_ps((void *)dst, mask, dst_idx_v, outputs[j],
                                      4);
        }
    }
}

Почти решает задачу:

Problem bn02-4: c/floats/intrinsics-image

Дан массив чисел типа float являющийся строкой изображения закодированного в RGB формате.

То есть строка состоит из 3*n чисел, каждая группа по три числа которых является значением соответствующих каналов очередного пикселя.

Порой при обработке изображения приходится менять местами каналы, возможно добавляя дополнительный alpha канал (например, из RGB в BGRA формат).

Напишите функцию void swap_line(const float *src, float *dst, unsigned n, const int order[4], float extra)

Принимающую на вход строку изображения формата RGB длины n и преобразующая согласно порядку описанному в массиве order (0 - Red, 1 - Green, 2 - Blue, 3 - Extra)

Гарантируется что и src и dst имеют дополнительно запас в 16 элементов слева и справа.

Тесты рассчитаны примерно чтобы:

Решения использующие 128 битные получали 0 баллов

Решения использующие 256 битные 50 баллов

Решения использующие AVX512 100 баллов

Возможно полезны инструкции: vpermps, andps, andnps, orps

Решение будет скомпилировано с флагами -O3 -march=native

 

Submit a solution

Language:	gcc - GNU C 11.3.0
Но выдает:

N	Result	Time (sec)	Score
1	OK	0.006	0 (0)
2	OK	0.004	0 (0)
3	OK	0.003	0 (0)
4	OK	0.004	0 (0)
5	OK	0.004	0 (0)
6	OK	0.004	0 (0)
7	Time-limit exceeded	>1.000	0 (50)
8	Time-limit exceeded	>1.000	0 (50)

попробуй ускорить код