Форум программистов, компьютерный форум, киберфорум
OpenMP
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.85/97: Рейтинг темы: голосов - 97, средняя оценка - 4.85
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
1

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

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

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

Имеется цикл вида:
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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.05.2012, 13:11
Ответы с готовыми решениями:

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

Распараллеливание циклов с использованием OpenMP C++
Доброго времени суток. (Нужен совет, так как разбираюсь с omp почти 3 дня и не хватает знанний) ...

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

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

41
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
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
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
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
05.05.2012, 14:40 4
В свойствах проекта Configuration Properties → C/C++ → Language
OpenMP включён?
У меня GCC и Linux. Но в MSVC тоже должно работать.
1
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
05.05.2012, 14:46  [ТС] 5
Включил. Спасибо большое!

Подскажите пожалуйста общую концепцию как на Ваш взгляд лучше реализовать мою изначальную задачу. Спасибо.
0
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
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
06.05.2012, 17:35 7
Очень многое зависит от того, что же там за "do something;"

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

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

Вот.

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

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

Добавлено через 10 секунд
слово for в pragma не писал, да. оно нужно?
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
06.05.2012, 17:41 9
Цитата Сообщение от qwrus Посмотреть сообщение
слово for в pragma не писал, да. оно нужно?
Нет, раз обе нити должны сделать все N по итераций цикла каждая, то не нужно. Просто показалось
1
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 17:42  [ТС] 10
Так что я такого не понимаю, что у меня ничего не работает?
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
06.05.2012, 17:45 11
Я OpenMP сам только начал осваивать, так что всех граблей назвать не смогу. Ну давай для начала хоть с факториалами попробуем ускорить. Хотя ждать, что 2 ядра выполнят в 2 раза больше работы не стоит, но хотя бы 1,5 раза в большинстве случаев получается легко.
1
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
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
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
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 18:34  [ТС] 14
А как включить оптимизацию?
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
06.05.2012, 18:35 15
Ну, если проект компилируется в режиме Release, то она, как правило, включена по умолчанию. В Debug по умолчанию выключена.
0
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 18:39  [ТС] 16
Скомпилировал вот без оптимизации, результат ужасный - если раньше выполнялось за 4 секунды, то сейчас за 25.
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
06.05.2012, 18:42 17
Ну, увеличение времени понятно, деление по модулю операция не быстрая. А результат в сравнении параллельно и нет как? У меня время практически одинаково. параллельный процентов 5 проигрывает всего.
1
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 19:00  [ТС] 18
Я же написал выше, что когда запускал без параллельного, то было 4 секунды. А с параллельным стало 25.

Добавлено через 2 минуты
Если закомментить деление по модулю, то будет 8 секунд.
0
Эксперт С++
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
06.05.2012, 19:01 19
А нельзя ли всё-таки с оптимизацией попробовать?
0
0 / 0 / 0
Регистрация: 10.03.2012
Сообщений: 24
06.05.2012, 19:02  [ТС] 20
Как проверить включена она или нет, и если нет, как включить?
0
06.05.2012, 19:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.05.2012, 19:02
Помогаю со студенческими работами здесь

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

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

Для распараллеливание процессов лучше пользоваться OpenMP или Win32?
Для распараллеливание процессов лучше пользоваться OpenMP или Win32? Называйте темы информативно

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru