2014 dxdy logo

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

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




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


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

#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
1771
Название темы вводит в заблуждение.
Дело тут не в gcc, а в openmp. Надо читать документацию, разбираться.

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


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

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


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

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


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

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

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


15/12/22
201
Действительно, достигается лишь видимость распараллеливания. В результатах одни нули, хотя, изредка встречаются и какие то значения. Похоже всё это время уходит именно на 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
9416
Цюрих
Где-то в коде проезд по памяти. Пока не поправите - проверять что-то еще бесполезно.

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


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

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


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

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

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


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


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

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


15/12/22
201
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
9416
Цюрих
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
4596
А почему переменная dv одна на всех?

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


15/12/22
201
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
9416
Цюрих
Missir в сообщении #1638647 писал(а):
я пробовал заводить для неё массив res[i] но это ни на что не влияет, видимо компилятор с этим справляется сам
При распараллеливании не должен справляться - переменная dv, объявленная вне цикла, shared (одна на все потоки), и запись в нее из разных потоков без синхронизации запрещена (тоже гонка). Но к проезду по памяти приводить не должно.
Missir в сообщении #1638647 писал(а):
max_norm никаких внешних функций не вызывает, внутри неё объявлено несколько небольших статических массивов и переменных
Статические переменные глобальны. В зависимости от того, как Вы их используете, как раз очень легко получить проезд по памяти или use after free.

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

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

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



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

Сейчас этот форум просматривают: granit201z


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

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