Проблема с использованием openmp с вложенными циклами for и встроенными функциями

#c #for-loop #openmp #nested-loops #intrinsics

#c #цикл for #openmp #вложенные циклы #встроенные функции

Вопрос:

Итак, у меня возникли небольшие проблемы с поиском наилучшего способа распараллеливания этих циклов for с использованием openmp. Я предполагаю, что наибольшая скорость была бы достигнута при распараллеливании среднего цикла, как я делаю здесь:

 for(i = 0; i < m/16*16; i =16){
    #pragma omp parallel for
        for(j = 0; j < m; j  ){

            C_column_start = C i j*m;

            c_1 = _mm_loadu_ps(C_column_start);
            c_2 = _mm_loadu_ps(C_column_start 4);
            c_3 = _mm_loadu_ps(C_column_start 8);
            c_4 = _mm_loadu_ps(C_column_start 12);

            for (k=0; k < n; k =2){

                A_column_start = A k*m;

                a_1 = _mm_loadu_ps(A_column_start i);
                a_2 = _mm_loadu_ps(A_column_start i 4);
                a_3 = _mm_loadu_ps(A_column_start i 8);
                a_4 = _mm_loadu_ps(A_column_start i 12);

                b_1 = _mm_load1_ps(A_column_start j);

                mul_1 = _mm_mul_ps(a_1, b_1);
                mul_2 = _mm_mul_ps(a_2, b_1);
                mul_3 = _mm_mul_ps(a_3, b_1);
                mul_4 = _mm_mul_ps(a_4, b_1);

                c_4 = _mm_add_ps(c_4, mul_4);
                c_3 = _mm_add_ps(c_3, mul_3);
                c_2 = _mm_add_ps(c_2, mul_2);
                c_1 = _mm_add_ps(c_1, mul_1);

                A_column_start =m;

                a_1 = _mm_loadu_ps(A_column_start i);
                a_2 = _mm_loadu_ps(A_column_start i 4);
                a_3 = _mm_loadu_ps(A_column_start i 8);
                a_4 = _mm_loadu_ps(A_column_start i 12);

                b_1 = _mm_load1_ps(A_column_start j);

                mul_1 = _mm_mul_ps(a_1, b_1);
                mul_2 = _mm_mul_ps(a_2, b_1);
                mul_3 = _mm_mul_ps(a_3, b_1);
                mul_4 = _mm_mul_ps(a_4, b_1);

                c_4 = _mm_add_ps(c_4, mul_4);
                c_3 = _mm_add_ps(c_3, mul_3);
                c_2 = _mm_add_ps(c_2, mul_2);
                c_1 = _mm_add_ps(c_1, mul_1);

            }


            _mm_storeu_ps(C_column_start, c_1);
            _mm_storeu_ps(C_column_start 4, c_2);
            _mm_storeu_ps(C_column_start 8, c_3);
            _mm_storeu_ps(C_column_start 12, c_4);

        }

    }
  

Однако в настоящее время это почти не ускоряет меня. Любые советы были бы замечательными. Я застрял на довольно долгое время.

Комментарии:

1. Вы пытались распараллелить внешний цикл?

2. Я сделал. Это также не дает мне никакого ускорения.

Ответ №1:

Прежде всего, вы уверены, что циклы распараллеливаются? Каков диапазон значений m ?

Когда все три вложенных цикла распараллеливаются и m достаточно велики (скажем, по крайней мере 16 или около того), тогда распараллеливание самого внешнего цикла будет наиболее выгодным. Распараллеливание внутренних циклов может привести к серьезным накладным расходам на разветвление omp parallel for .

Для низкого ускорения, вот некоторый контрольный список:

  1. Вы уверены, что все ядра используются? Проверьте что-то вроде диспетчера задач. Поскольку синхронизация отсутствует, за исключением неявного барьера omp parallel for , должны использоваться все ядра.
  2. m Это огромное число? И какова длина вычислений? Если m объем вычислений огромен, а объем вычислений невелик, параллельные накладные расходы из-за omp parallel for могут свести на нет преимущества распараллеливания. При распараллеливании внутреннего цикла количество отключений (например, m ) не должно быть огромным.
  3. Причиной может бытьложный общий доступ. Если ваш код изменяет большой объем памяти, это может привести к ложному распределению и ускорению может быть нанесен ущерб.