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

Распараллелить программу для решения дифференциальных уравнений - C++

Восстановить пароль Регистрация
 
denisberton
Сообщений: n/a
02.08.2012, 02:50     Распараллелить программу для решения дифференциальных уравнений #1
Здравствуйте, посетители форума.

Я пробую распараллелить следующий фрагмент кода:
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
    ...
    // начальная инициализация всех значений
    ...
    doubleVec F_vect;
    doubleVec G_plus_vec;
    doubleVec G_minus_vec;
    
    int n, k;
    
    // K iterations
    
    for (k = 1; k <= K; k++) 
    {
        mU[k][0] = u0;
        mG[k][0] = u0;
    }
    
 
    for (k = 1; k <= K; k++) 
    {
        for (n = 1; n <= N; n++) // N subintervals
        {
            double TnNew = T0 + n * deltaT;
            double Tn = TnNew - deltaT; // move to the next interval
            
            F_vect = (oFE.*F) (f, TnNew, Tn, mU[k-1][n-1], IF);
            G_plus_vec = (oFE.*G) (f, TnNew, Tn, mU[k][n-1], IG);
            G_minus_vec = mG[k-1][n]; // get from previous G_plus_vec
            
            mG[k][n] = G_plus_vec;
            
            for (int i = 0; i < size_u; i++)
            {
                // main formula
                F_vect[i] = F_vect[i] + G_plus_vec[i] - G_minus_vec[i];
            }
            
            mU[k][n] = F_vect;
            
        } // for (int n = 1; n <= N; n++)
    
    }
Здесь mU - глобальная матрица. На каждом шаге (k) вычисляется значение U.

Две основные сторчки:

F_vect = (oFE.*F) (f, TnNew, Tn, mU[k-1][n-1], IF);
G_plus_vec = (oFE.*G) (f, TnNew, Tn, mU[k][n-1], IG);

Вычисление функции F занимает обычно много времени.

Я реализовал для многопроцессорной машины (по времени все получилось).
Сделал так:

Корень 1: Вычисляет F, G, U_1_1, отправляет U_1_1 на Корень 2, продолжает вычислять (и отправлять) U_1_2, U_1_3...
Корень 2: Получает U_1_1, Вычисляет F, G, U_2_1, отправляет U_2_1 на Корень 3, поучает U_1_2, вычисляет U_2_2, ...
Корень 3: Получает U_2_1, Вычисляет F, G, U_3_1, отправляет U_3_1 на Корень 4, продолжает вычислять U_3_2, ...
и т. д.


Теперь пробую реализовать многопоточную версию следующим образом:

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    doubleVec F_vect;
    doubleVec G_plus_vec;
    doubleVec G_minus_vec;
    
    int iam, numt, limit, n, k;
    int isync[NUMBER_OF_THREADS];
    
    // K iterations
    
    for (k = 1; k <= K; k++) 
    {
        mU[k][0] = u0;
        mG[k][0] = u0;
    }
    #pragma omp parallel private (iam, numt, limit, k, F_vect, G_plus_vec, G_minus_vec)
    {
        iam = omp_get_thread_num ();
        numt = omp_get_num_threads ();
        limit = std::min(numt-1, N);
        isync[iam] = 0;
        #pragma omp barrier
        
        for (k = 1; k <= K; k++) 
        {
            if ((iam > 0) && (iam <= limit)) 
            {
                for (;isync[iam-1] == 0;) 
                {
                    #pragma omp flush (isync)
                }
                isync[iam-1] = 0;
                #pragma omp flush (isync)
            }
            
            #pragma omp for schedule(static) nowait
            for (n = 1; n <= N; n++) // N subintervals
            {
                double TnNew = T0 + n * deltaT;
                double Tn = TnNew - deltaT; // move to the next interval
                
                F_vect = (oFE.*F) (f, TnNew, Tn, mU[k-1][n-1], IF);
                G_plus_vec = (oFE.*G) (f, TnNew, Tn, mU[k][n-1], IG);
                G_minus_vec = mG[k-1][n]; // get from previous G_plus_vec
                
                //UGnext[n] = G_plus_vec;
                mG[k][n] = G_plus_vec;
                
                for (int i = 0; i < size_u; i++)
                {
                    // main formula
                    F_vect[i] = F_vect[i] + G_plus_vec[i] - G_minus_vec[i];
                }
                
                mU[k][n] = F_vect;
                
            } // for (int n = 1; n <= N; n++)
            
            if (iam < limit) 
            {
                for (;isync[iam]==1;) 
                {
                    #pragma omp flush (isync)
                }
                isync[iam] = 1;
                
                #pragma omp flush (isync)
            }
        
        }
    
    }
Честно говоря, метод подсмотрел тут.

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

Не могли бы вы посоветовать как можно распараллелить программу? Возможно, здесь совсем несложно, а я все усложняю?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.08.2012, 02:50     Распараллелить программу для решения дифференциальных уравнений
Посмотрите здесь:

Функция для численного интегрирования системы дифференциальных уравнений методом Рунге - Кутта C++
C++ Составить программу решения системы уравнений
Написать программу для решения системы уравнений с пом. матрицы C++
сделать программу для решения дифференциальных уравнений C++
Помогите исправить программу решения системы уравнений C++
C++ Помогите найти программу решения систем алгебраических уравнений методом Зейделя
Написать программу для решения системы двух уравнений C++
C++ Написать программу для решения системы уравнений методом Гаусса (c++)

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать тему
Опции темы

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