| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Циклы For и OpenMP |
| Автор: BrookBond 12.6.2013, 10:05 | ||
| Приветствую знатоков! Только начал изучать OpenMP и сразу попытался применить его на практике. Пишу прогу, которая в дальнейшем будет работать (сравнивать матрицы больших размеров) на многоядерном компе. Вот проблемная часть этой проги, где используется OpenMP и возникают непонятные мне действия. Код:
Проблема в том, что если внешний цикл по р запараллелить, то данные начинают смешиваться, выводятся хаотично так как показано на прикрепленном рисунке (самый правый столбец это значения внешнего цикла по р). А нужно чтобы они выводились последовательно, с начала то что считает первое ядро (0...3150), а затем второе (3151..6300), но чтоб считались параллельно. Подскажите пожалуйста, что добавить/убрать ? Прикреплен проект в Qt Creator, работаю на вин 7. |
| Автор: BrookBond 12.6.2013, 10:06 |
| Вот скрин работы проги |
| Автор: BrookBond 12.6.2013, 13:02 |
| Спасибо, сейчас как раз над этим работаю |
| Автор: Wuffur 18.6.2013, 16:14 | ||
По-моему надо просто написать:
Перед printf. А нет я не прав, надо еще один for запилить. |
| Автор: BrookBond 18.6.2013, 22:32 | ||
| Подскажите если знаете, вот такая проблема получается если использовать прагму. Первое ядро в цикле по р считает элементы от 0 до 3150, а второе 3151 - 6300. Но довольно часто получается, что второе ядро быстрее считает свою часть и в то время как первое ядро считает i-й элемент (внешний цикл) второе считает уже i+1 элемент и соответственно получается путаница в данных. Как сделать так чтобы второе ядро ждало завершения счета первого ядра и потом уже они вместе переходили бы на i+1 элемент?
|
| Автор: Wuffur 18.6.2013, 23:20 | ||||
| Как вариант сначала можно записать в массив, а потом в файл. То есть через указатели. Ждать пока ядра завершаться:
я уже сказал. Мне тут нравится документация: https://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Fcompiler%2Fref%2Fruompbar.htm И у меня это код на linux`е segfault`ится. Вот ещё, вроде можно с :
Так даже в том коде работать должно. http://stackoverflow.com/questions/10443528/is-there-an-implicit-barrier-after-omp-critical-section http://msdn.microsoft.com/ru-ru/library/b38674ky.aspx |
| Автор: BrookBond 19.6.2013, 11:57 | ||||
Подскажи пожалуйста код, а то никак не могу разобраться с барьером
При такой записи барьера результата нет, по прежнему идет перескок одного ядра на i+1 элемент, куда его поставить? |
| Автор: Wuffur 19.6.2013, 13:57 | ||
| Да , потому что потоки выполняются параллельно до барьера, синхронизируются и дальше выполняются параллельно, поэтому и перескакивает. Если выполняется дериктива #pragma omp critical, то компилятору говорится, что в этом участке кода нужно выполнять в один поток. Вся магия. То есть если printf запихнуть в
то всё должно быть нормально. Что происходит когда ставишь барьерную синхронизацию на 3150 элементе? Наверное программа распараллеливает for между задачи между ядрами - один выполняет от 1 до 1575 другой от 1576 до 3150, а после от 3151 до 4725 и от 4726 до 6300. В таком случае на 6300-ом элементе её ставить нет смысла. Барьерная синхронизация нужна бы была, если бы у вас элементы в printf() передавались бы переменные из других значений итератора цикла for и у вас выводились еще неинициализированные на каких-то шагах итерации значения переменных. Но это совершенно не влияет на порядок их вывода на стандартный поток. Без барьерной синхронизации всё не так однозначно, порядок выполнение параллельных команд может зависеть от состояния кэша и каких-то физических факторов, к примеру температуры процессора. Вывод сначала в массив был лучше просто вывода в файл или стандартный поток тем, что можно было бы записать произвольно, а в файл(хотя конечно можно и произвольно с fseek, fwrite) и в стандартный поток записывается по порядку. |
| Автор: BrookBond 19.6.2013, 14:45 | ||||||
Получается что прога зависает (останавливается).
На это не похоже. попробовал сделать так
Становится гораздо лучше, данные выводит почти что верно, но я использую printf лишь для того чтоб отслеживать какие значения записываются в Obmen3 . А при такой записи все равно в Obmen3 записываются не по порядку, а нужно чтобы в этот массив записывались данные в том же порядке как и при работе на одном ядре. Help.... |
| Автор: Wuffur 19.6.2013, 15:12 | ||
| А почему бы вам в массив не писать? То есть я не совсем понимаю, что там инициализировалось:
Дебагер вам в руки. |
| Автор: BrookBond 19.6.2013, 15:14 |
Так я же и записываю все данные сравнения в массив структур Obmen3, или что то не так делаю? |
| Автор: Wuffur 19.6.2013, 15:22 |
| Попробуйте раскомментить второй printf и проверить выполняются ли условия выражения if, если да, то проблема не внутри скобок. Не знаю, может барьерная синхронизация перед критической секцией поможет, но мне кажется вряд ли. У меня ваша программа даже под 10-ой студией не запускается. |
| Автор: Wuffur 19.6.2013, 17:06 | ||
Ну так printf пишет в стандартный поток, сделайте fprintf в критической секции будет писать в файл. |
| Автор: Wuffur 13.7.2013, 17:28 |
| Попробуйте еще #pragma omp single вначале, чтобы одна нить исполняла одну секцию кода и #pragma omp barrier #pragma omp master перед файловым выводом. |