OpenMP и оптимизация векторных операций - PullRequest
2 голосов
/ 30 марта 2012

Я сейчас использую алгоритм, который очень тяжелый, но чрезвычайно параллельный.

Я искал способы ускорить его и заметил, что самая медленная операция у меня - это мояФункция VecAdd (вызывается тысячи раз на векторе шириной 6000 или более).

Она реализована следующим образом:

bool VecAdd( float* pOut, const float* pIn1, const float* pIn2, unsigned int num )
{
    for( int idx = 0; idx < num; idx++ )
    {
        pOut[idx]   = pIn1[idx] + pIn2[idx];
    }
    return true;
}

Это очень простой цикл, но все дополнения могут бытьвыполняется параллельно.Мой первый вариант оптимизации состоит в том, чтобы перейти к использованию SIMD, так как я могу легко ускорить это почти в 4 раза.

Однако меня также интересует возможность использования OpenMP и его автоматическая обработка потока дляцикл (потенциально дает мне еще 4-кратное ускорение в общей сложности в 16 раз с SIMD).

Однако он действительно работает медленно.При прямом цикле обработка данных моего примера занимает около 3,2 секунды.Если бы я вставил

#pragma omp parallel for

перед циклом for, я предполагал, что он выделит несколько блоков дополнений к другим потокам.

К сожалению, в результате получается, что обработка данных моего примера занимает ~ 7 секунд.

Теперь я понимаю, что большая часть моей проблемы здесь будет вызвана накладными расходами при настройке потоков и т. Д.но я все еще удивляюсь, насколько медленнее это заставляет вещи работать.

Можно ли ускорить это, каким-либо образом предварительно настроив пул потоков, или я никогда не смогу бороться с этими издержками?

Есть какие-нибудь мысли по поводу того, могу ли я это сделатькрасиво с OpenMP будет высоко ценится!

1 Ответ

4 голосов
/ 30 марта 2012

Ваш цикл должен хорошо распараллеливаться с параллельным для #pragma omp.Тем не менее, я думаю, что проблема в том, что вы не должны распараллеливать на этом уровне.Вы сказали, что функция вызывается тысячи раз, но работает только на 6000 операций с плавающей запятой.Распараллелить на более высоком уровне, чтобы каждый поток отвечал за вызовы thounsands / 4 в VecAdd.Прямо сейчас у вас есть этот алгоритм:

  1. Элемент списка
  2. последовательное выполнение
  3. (повторное) начало потоков
  4. выполнение коротких вычислений
  5. синхронизировать потоки (в конце цикла for)
  6. вернуться к последовательному коду

Изменить его так, чтобы он был параллелен на максимально возможном уровне.

Пропускная способность памяти, конечно, имеет значение, но нет никакого способа, которым это могло бы привести к более медленному, чем последовательное выполнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...