2012-03-30 2 views
2

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

Я искал способы ускорить его, и я заметил, что самая медленная операция у меня есть моя функция 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 и автоматического потока цикла for (потенциально предоставляя мне дополнительный 4-кратный ускорение в общей сложности 16 раз с SIMD).

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

#pragma omp parallel for 

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

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

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

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

Любые мысли о совете относительно того, могу ли я хорошо прорисовать это с помощью OpenMP, будут очень благодарны!

+0

Общие реализации OpenMP будут создавать пул потоков заранее. –

+1

Чтобы быть уверенным, поскольку в вашем вопросе нигде не упоминается: у вас есть одно ядро ​​для каждой темы, не так ли? –

+0

Это не похоже на проблему с кешем, так как каждый массив имеет всего 6000 поплавков. Какую версию OpenMP вы используете? – devil

ответ

4

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

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

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

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

+0

Thats в значительной степени, как я подозревал. Ура! :) – Goz

Смежные вопросы