Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 59, средняя оценка - 4.63
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
#1

Распараллеливание с помощью OpenMP - C++

05.05.2012, 13:11. Просмотров 9258. Ответов 41
Метки нет (Все метки)

Здравствуйте, уважаемые участники форума!

Имеется цикл вида:
C++
1
2
3
4
for (i=1; i<number; i++)
{
  do something;
}
Цикл выполняется (замерил) за, к примеру, 7 секунд. Моя задача заключается в том, чтобы с помощью технологии OpenMP сделать так, чтобы 2 (или лучше 4) последовательные итерации выполнялись одновременно параллельно на двух процессорах (на обычном компьютере с процессором i5). Т.е. цель - сделать то же за в 2 (или 4) раза меньшее время. Пытался сделать с помощью директив #pragma omp parallel, не получилось, выполняется за те же 7 секунд.

Буду благодарен за помощь.

P.S. Также буду благодарен за любые другие, более профессиональные реализации данной задачи с использованием технологии OpenMP.

Добавлено через 3 часа 58 минут
В догонку еще вопрос.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <iostream>
#include <time.h>
#include "TimeCounter.h"
#include <omp.h>
 
using namespace std;
 
void mode (void)
{
    if (omp_in_parallel()) cout<<"Parallel"<<endl;
    else cout<<"Posl"<<endl;
}
 
int main (void)
{
    double start, end;
    int n;
    mode();
    start = omp_get_wtime();
    omp_set_nested(1);
#pragma omp parallel private(n)
    {
        n = omp_get_thread_num();
#pragma omp parallel 
        {
            cout<<"Part 1, thread "<<n<<' '<<omp_get_thread_num()<<endl;
            mode();
        }
    }
    omp_set_nested(0);
    #pragma omp parallel private(n)
    {
        n = omp_get_thread_num();
#pragma omp parallel 
        {
            cout<<"Part 2, thread "<<n<<' '<<omp_get_thread_num()<<endl;
        }
    }
    end = omp_get_wtime();
    cout<<end-start<<endl;;
#pragma omp parallel
    {
#pragma omp master
        {
            mode();
        }
    }
}
Функция mode() проверяет, выполняется ли последовательная или параллельная область. Запускаю - везде выводится что последовательная. Есть идеи, почему?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.05.2012, 13:11
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Распараллеливание с помощью OpenMP (C++):

Как выполнить распараллеливание с помощью OpenMP
Доброго дня. У меня есть две функции. void A(const vector &lt;double&gt; &amp;a){...

Работа с OpenMP. Распараллеливание цикла for
Доброго времени суток товарищи. При работе с OpenMP возник следующий вопрос...

Распараллеливание циклов с ипользованием OpenMP
Есть проблема , получился парадокс - время роботы программы с ...

Распараллеливание цикла For с использованием OpenMP
Всем привет. Задался целью изучить OpenMP, что бы в дальнейшем уметь...

Распараллеливание вычисления интеграла используя редукции (OpenMP)
Доброго времени суток, ребята! Ксть задача распараллелить процесс вычисления...

Для распараллеливание процессов лучше пользоваться OpenMP или Win32?
Для распараллеливание процессов лучше пользоваться OpenMP или Win32? ...

41
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
05.05.2012, 13:19 #2
Чем и как компилируется? У меня такие результаты:
Код
$ g++ omptest.cpp -o omptest -O3 -fopenmp
$ ./omptest

Posl
Part 1, thread Part 1, thread 0 01
Parallel
Part 1, thread 0 1
Parallel
 0
Parallel
Part 1, thread 1 1
Parallel
Part 2, thread Part 2, thread 10  00

0.00510692
Parallel
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
05.05.2012, 14:37  [ТС] #3
grizlik78, Microsoft Visual Studio 2008. Ctrl+F5

Добавлено через 5 минут
У меня результаты совершенно другие, везде последовательно пишет. Плюс к примеру в программе
C++
1
2
3
4
5
6
7
int count = 0;
omp_set_number_threads(100);
#pragma omp parallel reduction (+: count)
{
count++;
}
cout<<cout;
Программа должна создать 100 нитей, в каждой из них создать локальную копию переменной count, а после выполнения параллельной области сложить все копии count и получить 100. А у меня распараллеливания значит не происходит, так как она выводит 1.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
05.05.2012, 14:40 #4
В свойствах проекта Configuration Properties → C/C++ → Language
OpenMP включён?
У меня GCC и Linux. Но в MSVC тоже должно работать.
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
05.05.2012, 14:46  [ТС] #5
Включил. Спасибо большое!

Подскажите пожалуйста общую концепцию как на Ваш взгляд лучше реализовать мою изначальную задачу. Спасибо.
0
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:32  [ТС] #6
Опять же, простой такой вопрос. Вот у меня есть цикл

for (i=0; i<N; i++)
{
do something;
}

который выполняется к примеру за 7 секунд. делаем

omp_set_num_threads(2); //делаем чтобы выполнялось двумя нитями
#pragma omp parallel
{
for (i=0; i<N; i++)
{
do something;
}
}

по идее программа должна параллельно выполнить два одинаковых кода, то есть сделать в два раза больше действий за тоже самое время. А она у меня делает за в два раза большее время, т.е. за 14 секунд.

А к примеру если я в функции omp_set_num_threads() объявлю не 2, а 3 нити, то на делает не за 14 секунд, а за 10.

Вот я видимо чего-то капитально не понимаю, разъясните пожалуйста.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 17:35 #7
Очень многое зависит от того, что же там за "do something;"

Добавлено через 1 минуту
Кстати, в прагме не забыто слово for ещё?
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:39  [ТС] #8
do something в моей задаче, а именно в той, на которой я хочу научиться - это вычисление факториала числа 100.

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

Вот.

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

Добавлено через 1 минуту
слово for в pragma не писал, да. оно нужно?

Добавлено через 10 секунд
слово for в pragma не писал, да. оно нужно?
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 17:41 #9
Цитата Сообщение от qwrus Посмотреть сообщение
слово for в pragma не писал, да. оно нужно?
Нет, раз обе нити должны сделать все N по итераций цикла каждая, то не нужно. Просто показалось
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:42  [ТС] #10
Так что я такого не понимаю, что у меня ничего не работает?
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 17:45 #11
Я OpenMP сам только начал осваивать, так что всех граблей назвать не смогу. Ну давай для начала хоть с факториалами попробуем ускорить. Хотя ждать, что 2 ядра выполнят в 2 раза больше работы не стоит, но хотя бы 1,5 раза в большинстве случаев получается легко.
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:53  [ТС] #12
хорошо. мой код пока такой

double start, end;
start = omp_get_wtime();
int i, k, g = 1;
omp_set_num_threads(2);
#pragma omp parallel
{
for (i = 0; i<100000; i++)
{
for (k = 1; k<1000; k++)
{
g = g*k;
}
}
}
end = omp_get_wtime();
cout<<end-start<<endl;

По нашему замыслу эта прога должна работать ну максимум в 1,5 раза больше, чем просто

for (i = 0; i<100000; i++)
{
for (k = 1; k<1000; k++)
{
g = g*k;
}
}

Но вот не работает.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 18:31 #13
Здесь все нити работают с одной и той же переменной g, изменяя её. Поэтому процессору надо постоянно синхронизировать значение этой переменной между ядрами. Промежуточные результаты стоить делать принадлежащими только одной нити, указав, например, private(g) в прагме. Переменные цикла по умолчанию приватные.
Но вообще пример не очень хороший, так как оптимизатор может его сильно изменить в зависимости от режима компиляции.
Предлагаю несколько модифицировать и сравнить быстродействие и результат на таком коде:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <omp.h>
 
using namespace std;
 
int const NPROC = 2;
int results[NPROC];
 
int main()
{
    double start, end;
    start = omp_get_wtime();
    int i, k, g;
 
    omp_set_num_threads(NPROC);
 
#pragma omp parallel private(g)
    {
        g = 1;
        for (i = 0; i<100000; i++)
        {
            for (k = 1; k<10000; k++)
            {
                g = g*k % 654321;
            }
        }
        results[omp_get_thread_num()] = g;
    }
 
    end = omp_get_wtime();
 
    cout << "time: " << end-start << endl;
    
    for (int i = 0; i < NPROC; ++i)
        cout << "r[" << i << "] = " << results[i] << endl;
    
    return 0;
}
Компилировать лучше с включённой оптимизацией.
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 18:34  [ТС] #14
А как включить оптимизацию?
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 18:35 #15
Ну, если проект компилируется в режиме Release, то она, как правило, включена по умолчанию. В Debug по умолчанию выключена.
0
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 18:39  [ТС] #16
Скомпилировал вот без оптимизации, результат ужасный - если раньше выполнялось за 4 секунды, то сейчас за 25.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 18:42 #17
Ну, увеличение времени понятно, деление по модулю операция не быстрая. А результат в сравнении параллельно и нет как? У меня время практически одинаково. параллельный процентов 5 проигрывает всего.
1
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 19:00  [ТС] #18
Я же написал выше, что когда запускал без параллельного, то было 4 секунды. А с параллельным стало 25.

Добавлено через 2 минуты
Если закомментить деление по модулю, то будет 8 секунд.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
06.05.2012, 19:01 #19
А нельзя ли всё-таки с оптимизацией попробовать?
0
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 19:02  [ТС] #20
Как проверить включена она или нет, и если нет, как включить?
0
06.05.2012, 19:02
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.05.2012, 19:02
Привет! Вот еще темы с решениями:

OpenMP. Время выполнения программы больше чем без OpenMP
Сегодня первый раз сел за OpenMP. Читаю на сайте майкрософта как работает этот...

OpenMP распараллеливание цикла
Привет кодеры! Нужна ваша помощь. У меня есть код который нужно распараллелить...

Параллельная программа для метода холецкого с помощью openMp и mpi
Товарищи,помогите пожалуйста с параллельным программированием: надо написать...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru