Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 59, средняя оценка - 4.63
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
05.05.2012, 13:11     Распараллеливание с помощью OpenMP #1
Здравствуйте, уважаемые участники форума!

Имеется цикл вида:
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() проверяет, выполняется ли последовательная или параллельная область. Запускаю - везде выводится что последовательная. Есть идеи, почему?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.05.2012, 13:11     Распараллеливание с помощью OpenMP
Посмотрите здесь:

Распараллеливание C++
Как выполнить распараллеливание с помощью OpenMP C++
Распараллеливание алгоритмов C++
Распараллеливание циклов с ипользованием OpenMP C++
распараллеливание C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
05.05.2012, 13:19     Распараллеливание с помощью OpenMP #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
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
05.05.2012, 14:37  [ТС]     Распараллеливание с помощью OpenMP #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.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
05.05.2012, 14:40     Распараллеливание с помощью OpenMP #4
В свойствах проекта Configuration Properties → C/C++ → Language
OpenMP включён?
У меня GCC и Linux. Но в MSVC тоже должно работать.
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
05.05.2012, 14:46  [ТС]     Распараллеливание с помощью OpenMP #5
Включил. Спасибо большое!

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

Вот я видимо чего-то капитально не понимаю, разъясните пожалуйста.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 17:35     Распараллеливание с помощью OpenMP #7
Очень многое зависит от того, что же там за "do something;"

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

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

Вот.

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

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

Добавлено через 10 секунд
слово for в pragma не писал, да. оно нужно?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 17:41     Распараллеливание с помощью OpenMP #9
Цитата Сообщение от qwrus Посмотреть сообщение
слово for в pragma не писал, да. оно нужно?
Нет, раз обе нити должны сделать все N по итераций цикла каждая, то не нужно. Просто показалось
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:42  [ТС]     Распараллеливание с помощью OpenMP #10
Так что я такого не понимаю, что у меня ничего не работает?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 17:45     Распараллеливание с помощью OpenMP #11
Я OpenMP сам только начал осваивать, так что всех граблей назвать не смогу. Ну давай для начала хоть с факториалами попробуем ускорить. Хотя ждать, что 2 ядра выполнят в 2 раза больше работы не стоит, но хотя бы 1,5 раза в большинстве случаев получается легко.
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:53  [ТС]     Распараллеливание с помощью OpenMP #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;
}
}

Но вот не работает.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 18:31     Распараллеливание с помощью OpenMP #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;
}
Компилировать лучше с включённой оптимизацией.
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 18:34  [ТС]     Распараллеливание с помощью OpenMP #14
А как включить оптимизацию?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 18:35     Распараллеливание с помощью OpenMP #15
Ну, если проект компилируется в режиме Release, то она, как правило, включена по умолчанию. В Debug по умолчанию выключена.
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 18:39  [ТС]     Распараллеливание с помощью OpenMP #16
Скомпилировал вот без оптимизации, результат ужасный - если раньше выполнялось за 4 секунды, то сейчас за 25.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 18:42     Распараллеливание с помощью OpenMP #17
Ну, увеличение времени понятно, деление по модулю операция не быстрая. А результат в сравнении параллельно и нет как? У меня время практически одинаково. параллельный процентов 5 проигрывает всего.
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 19:00  [ТС]     Распараллеливание с помощью OpenMP #18
Я же написал выше, что когда запускал без параллельного, то было 4 секунды. А с параллельным стало 25.

Добавлено через 2 минуты
Если закомментить деление по модулю, то будет 8 секунд.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
06.05.2012, 19:01     Распараллеливание с помощью OpenMP #19
А нельзя ли всё-таки с оптимизацией попробовать?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.05.2012, 19:02     Распараллеливание с помощью OpenMP
Еще ссылки по теме:

Распараллеливание циклов C++
Работа с OpenMP. Распараллеливание цикла for C++
C++ Для распараллеливание процессов лучше пользоваться OpenMP или Win32?

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

Или воспользуйтесь поиском по форуму:
qwrus
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 19:02  [ТС]     Распараллеливание с помощью OpenMP #20
Как проверить включена она или нет, и если нет, как включить?
Yandex
Объявления
06.05.2012, 19:02     Распараллеливание с помощью OpenMP
Ответ Создать тему
Опции темы

Текущее время: 05:47. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru