2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 не работает распараллеливание в gcc
Сообщение07.05.2024, 22:28 


15/12/22
198
Есть такой фрагмент кода, в котором я пытаюсь распаралелить цикл:
Код:

#include <omp.h>
.................................

#pragma omp parallel for num_threads(2)
for (i=0; i<sampl-1; i++)
{ printf ("iteration %d, thread=%d\n", i, omp_get_thread_num());
  x[i*sampl+i]=0.0;
  for (j=i+1; j<sampl; j++)
   { dv=max_norm(xyz+i*N_atom*3, xyz+j*N_atom*3, iel, N_atom, N_perm);
     x[i*sampl+j]=sqrt((Sx[i]+Sx[j]-2*dv)/N_atom); x[j*sampl+i]=x[i*sampl+j]; 
   }
}


компилирую с опцией -fopenmp

Как ни странно, но всё работает, на экране попеременно выводятся разные потоки и в разноброд, номера итераций.
Время вычислений сокращается в 1,5 раза. Наверное, если убрать printf(), то сократится почти в 2.
Но вот проблема, стоит только закоментировать printf() и время вычислений возрастает в 1,5 раза, становится точно таким, как в 1 потоке. В чём может быть дело?

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 08:56 
Заслуженный участник


18/09/21
1764
Название темы вводит в заблуждение.
Дело тут не в gcc, а в openmp. Надо читать документацию, разбираться.

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 11:53 


01/09/14
584
Missir
Вы бы полностью код выложили, может кто подебажит.

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 14:53 
Заслуженный участник


16/02/13
4214
Владивосток
Сильно подозреваю, что распараллеливание достигается исключительно за счёт операций ввода-вывода (print). Чисто вычислительные операции распараллеливаются вообще не очень хорошо. Посмотрите, у вас точно задействованы несколько процессоров?

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 15:42 
Заслуженный участник
Аватара пользователя


16/07/14
9202
Цюрих
Чисто вычислительные операции хорошо параллелятся, но x[j*sampl+i] выглядит как хорошее место чтобы упереться в чтение из памяти. Попробуйте поправить код так, чтобы чтения были в основном последовательными.

Какие абсолютные времена получаются с OMP и без, с printf и без?

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 15:55 


15/12/22
198
Действительно, достигается лишь видимость распараллеливания. В результатах одни нули, хотя, изредка встречаются и какие то значения. Похоже всё это время уходит именно на printf(). Как тогда распараллелить этот цикл. Какие требования я нарушил? Ведь если с printf() всё работает, значит дело не в omp а в моём цикле

-- 08.05.2024, 16:07 --

mihaild в сообщении #1638488 писал(а):
Какие абсолютные времена получаются с OMP и без, с printf и без?


без omp но с printf() 4.9s, без printf() почти столько же
с omp и с printf() сейчас вылетело free(): invalid pointer Аварийный останов и время 4.4s
второй запуск double free or corruption (out) Аварийный останов 3.6s
трети запуск double free or corruption (out) Аварийный останов 3.4s

В общем я наверное раньше не замечал этой ошибки и казалось что быстрее.

Если закоментировать printf() то время увеличивается до 4.8s, ошибка пропадает, но результаты выдаёт неверные, сплошные нули

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 17:28 
Заслуженный участник
Аватара пользователя


16/07/14
9202
Цюрих
Где-то в коде проезд по памяти. Пока не поправите - проверять что-то еще бесполезно.

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 18:51 


15/12/22
198
mihaild
а может такое возникать из-за многопоточности? ведь в однопоточном варианте с памятью я всё отладил, и проблем никогда не было

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 19:16 
Заслуженный участник
Аватара пользователя


16/07/14
9202
Цюрих
Может, если где-то в цикле гонка. Без полного текста программы (например что делает max_norm) ничего сказать нельзя.
Выложите действительно релевантную часть кода целиком (и желательно с нормальным форматированием).

А так - thread и address sanitizer'ы Вам в помощь.

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение08.05.2024, 21:36 
Аватара пользователя


23/05/20
396
Беларусь
Missir в сообщении #1638503 писал(а):
а может такое возникать из-за многопоточности? ведь в однопоточном варианте с памятью я всё отладил, и проблем никогда не было


Скорей всего вы полностью правы. Может вам поможет мой опыт. Это начало 2000-х, драйвера для интернета на intel-процессоры. Дело было давно, поэтому могу подсказать лишь принцип. Плюс сейчас это может быть не актуальная информация, т.е. эта проблема решена.
У меня в процедуре разветвление вычислений приводило к тому, что, если нить начинает выполняться на соседнем ядре, то у нее теряется связь с локальными данными процедуры, и в драйвере возникала ошибка. Я избавился от этой ошибки тем, что определял внутри распаралеленного участка локальные данные, с которыми нить работает, а в локальные данные процедуры вычисленные значение передавал через разъименование указателя.

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение10.05.2024, 15:39 


15/12/22
198
100 раз всё перепроверил, и обнаружил, что внутренний цикл распараллеливается без проблем
Код:
for (i=0; i<sampl-1; i++)
{
  x[i*sampl+i]=0.0;
  #pragma omp parallel for num_threads(2)
  for (j=i+1; j<sampl; j++)
   { printf ("iteration %d, thread=%d\n", i, omp_get_thread_num());
     dv=max_norm(xyz+i*N_atom*3, xyz+j*N_atom*3, iel, N_atom, N_perm);
     x[i*sampl+j]=sqrt((Sx[i]+Sx[j]-2*dv)/N_atom); x[j*sampl+i]=x[i*sampl+j]; 
   }
}

все результаты выдаёт верные, работает судя по printf() на обоих ядрах
но проблема в том, что внутренний цикл параллелить невыгодно, т.к. слишком мелкие задачи,
из-за накладных расходов, общее время выполнения кода не уменьшается а только возрастает

Возникает резонный вопрос, что предпринять, чтобы корректно распараллеливался именно внешний цикл, а не внутренний?

-- 10.05.2024, 15:41 --

p.s: правильно форматировать код не получается, писал в теге lang="С", но это ничего не даёт

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение10.05.2024, 15:46 
Заслуженный участник
Аватара пользователя


16/07/14
9202
Цюрих
StepV в сообщении #1638510 писал(а):
если нить начинает выполняться на соседнем ядре, то у нее теряется связь с локальными данными процедуры, и в драйвере возникала ошибка
Это либо Вы писали на чем-то низкоуровневом, либо ошибка в библиотеке / компиляторе. OMP такого делать не должно.
Missir в сообщении #1638639 писал(а):
Возникает резонный вопрос, что предпринять, чтобы корректно распараллеливался именно внешний цикл, а не внутренний?
Для начала - выложить весь релевантный код. Объявление и выделение памяти для всех переменных, вызываемые функции и т.д. Потом поправить ошибки - падение при параллелизации во внешнем цикле свидетельствует о том, что где-то в коде есть ошибка, которая просто в силу везения не проявляется в других режимах.
После этих исправлений можно будет разбираться дальше с тем, что параллелится, а что нет.
(хотя в любом случае сразу советую попробовать избавиться от x[j*sampl+i])

-- 10.05.2024, 14:49 --

Теги пишутся вот так: [syntax lang="c"]
Используется синтаксис C
for (i=0; i<sampl-1; i++)
{
  x[i*sampl+i]=0.0;
  #pragma omp parallel for num_threads(2)
  for (j=i+1; j<sampl; j++)
   { printf ("iteration %d, thread=%d\n", i, omp_get_thread_num());
     dv=max_norm(xyz+i*N_atom*3, xyz+j*N_atom*3, iel, N_atom, N_perm);
     x[i*sampl+j]=sqrt((Sx[i]+Sx[j]-2*dv)/N_atom); // Вот тут очень стоило добавить новую строку
     x[j*sampl+i]=x[i*sampl+j];
   }
}
 

Но для чтения разбиение на строки важнее, чем подсветка.

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение10.05.2024, 16:31 
Заслуженный участник


04/05/09
4589
А почему переменная dv одна на всех?

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение10.05.2024, 17:04 


15/12/22
198
venco в сообщении #1638645 писал(а):
А почему переменная dv одна на всех?


я пробовал заводить для неё массив res[i] но это ни на что не влияет, видимо компилятор с этим справляется сам

-- 10.05.2024, 17:16 --

mihaild в сообщении #1638640 писал(а):
Объявление и выделение памяти для всех переменных, вызываемые функции и т.д.

max_norm никаких внешних функций не вызывает, внутри неё объявлено несколько небольших статических массивов и переменных,
типы __m128, alignas(32) float, double, uint64_t, входные массивы внутри неё не модифицируются, из них только считываются данные,
динамического выделения или перераспределения памяти в ней нет, ну и понятно, что в основном, там используется sse

 Профиль  
                  
 
 Re: не работает распараллеливание в gcc
Сообщение10.05.2024, 17:25 
Заслуженный участник
Аватара пользователя


16/07/14
9202
Цюрих
Missir в сообщении #1638647 писал(а):
я пробовал заводить для неё массив res[i] но это ни на что не влияет, видимо компилятор с этим справляется сам
При распараллеливании не должен справляться - переменная dv, объявленная вне цикла, shared (одна на все потоки), и запись в нее из разных потоков без синхронизации запрещена (тоже гонка). Но к проезду по памяти приводить не должно.
Missir в сообщении #1638647 писал(а):
max_norm никаких внешних функций не вызывает, внутри неё объявлено несколько небольших статических массивов и переменных
Статические переменные глобальны. В зависимости от того, как Вы их используете, как раз очень легко получить проезд по памяти или use after free.

Попробуйте заменить max_norm на return 0; - скорее всего падение исчезнет. Если так - то значит причина связана с ее реализацией, и не видя кода угадать нельзя. Если не исчезнет - то значит замените, и выложите остальной релевантный код).

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 30 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group