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

С++. OpenMp. Flops. Увеличить скорость перемножение матриц

19.03.2013, 14:29. Показов 2246. Ответов 1
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. В универе стоит задача - написать программу для перемножения матриц с максимальной производительностью (flops) для дальнейшего использования с OpenMP. Использую стандартный алгоритм с некоторыми модификациями.
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
void Test2(int n, int threads)
{
    double* result = new double[n*n];
    double* A = new double[n*n];
    double* B = new double[n*n];
 
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            result[i*n+j] = 0;
 
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            A[i*n+j] = i+1;
 
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            B[j*n+i] = 1.0/(j+1);
    int i,j,k;
    double *indres,*indA,*indB;
    long start = clock();
 
#pragma omp parallel num_threads(threads) private(i,j,k) shared(result,A,B)
    {
#pragma omp for schedule(dynamic,50)
    for ( i = 0; i < n; i++)
    {
        indres = result+i*n;
        for ( j = 0; j < n; j++,indres++)
        {
            indB = B+j*n;
            indA = A+i*n;
            for(k =0; k < n; k++,indA++,indB++)
                *(indres) += *(indA)* *(indB);
        }
    }
    }
 
    double time = (clock() - start)*0.001;
 
    cout<<"Time - "<<fixed<<time<<" sec"<<endl;
 
    cout<<"Perfomance - "<<fixed<<2*((double)n/time)*((double)n*(double)n/1000000.0)<<" MegaFlops\n";
    cout<<fixed<<result[0];
    cout<<fixed<<"\t"<<result[n-1]<<endl;
    cout<<fixed<<result[(n-1)*n];
    cout<<fixed<<"\t"<<result[(n-1)*n+n-1]<<endl;
    cout<<"Threads count = "<<threads<<endl;
    
        delete[] result;
        delete[] A;
        delete[] B;
}
Можно ли ещё увеличить производительность, не меняя сам алгоритм на http://ru.wikipedia.org/wiki/Алгоритм_Штрассена
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.03.2013, 14:29
Ответы с готовыми решениями:

Перемножение матриц блоками. OpenMP
Помогите до работать программу. Необходимо чтобы каждый поток отдельно брал строку или столбец...

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

Возведение матриц в степени, перемножение и сложение матриц
Даны 3-ех элементные вещественные векторы x и y и квадратные матрицы A и B. Вычислить: (A 2 * x,...

Перемножение матриц
Помогите пожалуйста написать программу в которой будет содержаться функция для перемножения двух...

1
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
23.03.2013, 13:38  [ТС] 2
Улучшил его маленько. Версия для Windows сейчас выглядит так
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <omp.h>
#include <time.h>
 
using namespace std;
 
double const M_PI = 3.1415926535897932384626433832795;
 
 
void Test2(int n, int threads)
{
    double* result = new double[n*n];
    double* A = new double[n*n];
    double* B = new double[n*n];
 
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            result[i*n+j] = 0;
 
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            A[i*n+j] = i+1;
 
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            B[j*n+i] = 1.0/(j+1);
    int i,j,k;
    double *indres,*indA,*indB;
    long start = clock();
 
#pragma omp parallel num_threads(threads) private(i,j,k) shared(result,A,B)
    {
#pragma omp for schedule(dynamic,50)
        for ( i = 0; i < n; i++)
    {
        indres = result+i*n;
        for ( j = 0; j < n; indres++)
        {
            indB = B+(j++)*n;
            indA = A+i*n;
            for(k =0; k < n; k+=25)
            {
                double temp = 0;
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                temp += *(indA++)* *(indB++);
                *(indres) += temp;
            }
        }
    }
    }
 
    double time = (clock() - start)*0.001;
 
    cout<<"Time - "<<fixed<<time<<" sec"<<endl;
 
    cout<<"Perfomance - "<<fixed<<2*((double)n/time)*((double)n*(double)n/1000000.0)<<" MegaFlops\n";
    cout<<fixed<<result[0];
    cout<<fixed<<"\t"<<result[n-1]<<endl;
    cout<<fixed<<result[(n-1)*n];
    cout<<fixed<<"\t"<<result[(n-1)*n+n-1]<<endl;
    cout<<"Threads count = "<<threads<<endl;
    
        delete[] result;
        delete[] A;
        delete[] B;
}
 
int main(int argc, char **argv)
{
    
    int n = 2000;
    int threads = 2;
 
//Задание 2
    
    Test2(n, threads);
//Задание 2
    return 0;       
}
По логике вещей тут ошибка...ибо переменные
C++
1
double *indres,*indA,*indB;
должны быть в разделе private...но стоит их туда переместить, производительность падает примерно в 2 раза. Такое происходит только у меня на компе...под виндой. На кластере факультета всё норм.
p.s. до сих пор жду ваших откликов
0
23.03.2013, 13:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.03.2013, 13:38
Помогаю со студенческими работами здесь

Перемножение матриц
Построить матрицу С=А*В*В, где А - прямоугольная матрица размера n x m (4 x 3) , а В квадратная...

Перемножение матриц
С умножением беда совсем...Причем последний столбец нормальный, а остальные нет. Помогите,...

Перемножение матриц
Помогите пожалуйста сделать ассемблеровскую вставку для перемножения матриц. Есть функция : ...

Перемножение матриц
Помогите найти ошибку. Матрицы перемножает но выводит (Как я понимаю переполненные переменные...


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

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