Параллельное приложение имеет случайное поведение - PullRequest
4 голосов
/ 21 июня 2011

Я пишу программу на C, использующую pthreads для вычисления паттерна волнового фронта на двумерной матрице.Чтобы добиться хорошей производительности, я распределяю несколько строк в каждом потоке чередующимся образом, например так:

thread 0 ------------------

Тема 1 ------------------

Тема 2 ------------------

Тема 3 ------------------

Тема 0 ------------------

Тема 1 ------------------

Тема 2 -----------------

поток 3 ------------------

и т. Д.

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

поток 0 -----------

поток 1 ------

поток 2 ---

так, что всегда ряд i должен отставать от ряда i - 1. Надеюсь, вы понимаете идею.Я реализовал эту идею и тестирую ее на машине, которая представляет собой двухъядерную систему.Я испытываю странное поведение.Результаты рассчитываются правильно, но время выполнения колеблется в любом месте от 8 раз меньше, чем последовательное время и до больше, чем последовательное время.Практически, последовательное время для матрицы 12000 x 12000 составляет 16 секунд, а время параллельного запуска составляет от 2 до 17 секунд и часто отличается в двух последовательных прогонах.

Моя первоначальная идея заключалась в том, что эта проблема оченьчувствительность к локальности, поэтому, конечно, я могу получить плохую производительность, скажем, поток 0 и поток 1 запланированы на разных физических процессорах.Оглядываясь в / proc / cpuinfo, я пришел к выводу, что ядра отображаются так, что 0, 2, 4, 6 находятся на процессоре 0, а 1, 3, 5, 7 - на процессоре 1. Затем, при создании потока, я имеюиспользовал pthread_setaffinity_np, чтобы установить сродство к потокам на правильных ядрах.Однако ничего не меняется.Я также попытался использовать pthread_attr_setaffinity_np, а также sched_setaffinity, но получаю то же случайное время выполнения.

Либо ядро ​​игнорирует мои вызовы аффинности, либо это не проблема.Я действительно надеюсь, что кто-то может помочь мне, поскольку у меня закончились идеи.Спасибо.

1 Ответ

7 голосов
/ 21 июня 2011

Ядро не игнорирует ваши аффинные вызовы, это просто не проблема.

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

Попробуйте создать куски данных размером в одну строку (64 байта) Попробуйте сделать так, чтобы поток 0 проходил через 64 ​​байта, и только после этого поток 1 будет читать с того же места - и так далее.

...