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

OpenMP и SIMD - C++

Восстановить пароль Регистрация
 
Saky
0 / 0 / 0
Регистрация: 16.12.2015
Сообщений: 33
01.06.2016, 09:59     OpenMP и SIMD #1
Добрый день. Не могу исправить код, чтобы использовалось 4 ядра, а не 1. В функцию proizv нужно добавить распараллеливание вычислений с помощью 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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctime>
#include <locale.h>
#include <xmmintrin.h>
 
void create(double *mas, int x) {  //создание матрицы
    for (int i = 0; i < x; i++)
        for (int j = 0; j < x; j++) {
            *(mas + i*x + j) = rand() % 10 + 1;
        }
}
 
void transp(double *mas, int x) {  //транспонирование
    double a;
    for (int i = 0; i < x; i++)
        for (int j = i; j < x; j++) {
            a = mas[j*x + i];
            mas[j*x + i] = mas[i*x + j];
            mas[i*x + j] = a;
        }
}
 
double *proizv(double *mas1, double*mas2, int x) {  //произведение после транспонирования
    double *mas3; float sum;
    __m128 *a, *b;
    __m128 c, d;
    a = (__m128 *)mas1;
    b = (__m128 *)mas2;
    mas3 = (double *)_mm_malloc(x*x*sizeof(double), 16);
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            d = _mm_set_ps1(0);
            for (int k = 0; k < (x / 4); k++) {
                c = _mm_mul_ps(a[i*x / 4 + k], b[j*x / 4 + k]);
                d = _mm_add_ps(d, c);
            }
            c = _mm_movehl_ps(c, d);
            d = _mm_add_ps(d, c);
            c = _mm_shuffle_ps(d, d, 1);
            d = _mm_add_ss(d, c);
            _mm_store_ss(&sum, d);
            mas3[i*x + j] = sum;
        }
    }
    return mas3;
}
 
int main() {
    srand(time(0));
    int i, x;
    double *mas1, *mas2, *mas3;
    float start_time, end_time;
    printf("Vvedite razmernost' matric\n");
    scanf("%d", &x);
    mas1 = (double *)_mm_malloc(x*x*sizeof(double), 16);
    mas2 = (double *)_mm_malloc(x*x*sizeof(double), 16);
    create(mas1, x);
    create(mas2, x);
    transp(mas2, x);
    start_time = clock();
    mas3 = proizv(mas1, mas2, x);
    end_time = clock();
    float search_time = (end_time - start_time) / 1000;
    printf("runtime = %.1f", search_time);
    _mm_free(mas1);
    _mm_free(mas2);
    _mm_free(mas3);
    _getch();
}
Добавлено через 10 минут
Пыталась изменить на это:
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
double *proizv(double *mas1, double*mas2, int x) {  //произведение после транспонирования
    double *mas3; float sum;
    __m128 *a, *b;
    __m128 c, d;
    a = (__m128 *)mas1;
    b = (__m128 *)mas2;
    mas3 = (double *)_mm_malloc(x*x*sizeof(double), 16);
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            d = _mm_set_ps1(0);
#pragma omp parallel
            {
#pragma omp for
                for (int k = 0; k < (x / 4); k++) {
                    c = _mm_mul_ps(a[i*x / 4 + k], b[j*x / 4 + k]);
                    d = _mm_add_ps(d, c);
                }
            }
            c = _mm_movehl_ps(c, d);
            d = _mm_add_ps(d, c);
            c = _mm_shuffle_ps(d, d, 1);
            d = _mm_add_ss(d, c);
            _mm_store_ss(&sum, d);
            mas3[i*x + j] = sum;
        }
    }
    return mas3;
}
Но время выполнения с 5 секунд увеличивается до 18

Добавлено через 12 минут
При подобном варианте:
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
double *proizv(double *mas1, double*mas2, int x) {  //произведение после транспонирования
    double *mas3; float sum; int i, j;
    __m128 *a, *b;
    __m128 c, d;
    a = (__m128 *)mas1;
    b = (__m128 *)mas2;
    mas3 = (double *)_mm_malloc(x*x*sizeof(double), 16);
#pragma omp parallel
    {
#pragma omp for
        for (i = 0; i < x; i++) {
            for (j = 0; j < x; j++) {
                d = _mm_set_ps1(0);
                for (int k = 0; k < (x / 4); k++) {
                    c = _mm_mul_ps(a[i*x / 4 + k], b[j*x / 4 + k]);
                    d = _mm_add_ps(d, c);
                }
            }
            c = _mm_movehl_ps(c, d);
            d = _mm_add_ps(d, c);
            c = _mm_shuffle_ps(d, d, 1);
            d = _mm_add_ss(d, c);
            _mm_store_ss(&sum, d);
            mas3[i*x + j] = sum;
        }
    }
    return mas3;
}
Выполняется 1,4 секунды, но заканчивается ошибкой
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.06.2016, 09:59     OpenMP и SIMD
Посмотрите здесь:

C++ Вопросы по OpenMP
C++ Цикл for и OpenMP
C++ не работает openmp
C++ Оптимизация кода с использование SIMD
Параллельность в openMP C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
AlexVRud
414 / 143 / 36
Регистрация: 04.07.2014
Сообщений: 415
01.06.2016, 10:13     OpenMP и SIMD #2
Saky, а тебя не смущает, что c и d вычисляются последовательно, на каждом шаге? В таком варианте алгоритма, не один из циклов не может быть распараллелен.
nonedark2008
624 / 502 / 92
Регистрация: 28.07.2012
Сообщений: 1,343
01.06.2016, 10:16     OpenMP и SIMD #3
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Saky Посмотреть сообщение
ыполняется 1,4 секунды, но заканчивается ошибкой
Общие переменные, в которые что-то присваивается, нужно указывать явно в директиве.
Попробуй так:
убери строчку 8, в 10 - "#pragma omp parallel for", а переменные c, d внеси под первый цикл.
AlexVRud
414 / 143 / 36
Регистрация: 04.07.2014
Сообщений: 415
01.06.2016, 10:22     OpenMP и SIMD #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Только сеёчас заметил что у тебя блок съехал
C++
1
2
3
4
5
6
            c = _mm_movehl_ps(c, d);
            d = _mm_add_ps(d, c);
            c = _mm_shuffle_ps(d, d, 1);
            d = _mm_add_ss(d, c);
            _mm_store_ss(&sum, d);
            mas3[i*x + j] = sum;
Добавлено через 4 минуты
Возьми первый вариант, паралелить можно только цикл по i. И как выше сказали, определение временных переменных (c,d,sum) внеси внутрь этого цикла
Saky
0 / 0 / 0
Регистрация: 16.12.2015
Сообщений: 33
01.06.2016, 10:38  [ТС]     OpenMP и SIMD #5
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Общие переменные, в которые что-то присваивается, нужно указывать явно в директиве.
Попробуй так:
убери строчку 8, в 10 - "#pragma omp parallel for", а переменные c, d внеси под первый цикл.
Цитата Сообщение от AlexVRud Посмотреть сообщение
Только сеёчас заметил что у тебя блок съехал
C++
1
2
3
4
5
6
            c = _mm_movehl_ps(c, d);
            d = _mm_add_ps(d, c);
            c = _mm_shuffle_ps(d, d, 1);
            d = _mm_add_ss(d, c);
            _mm_store_ss(&sum, d);
            mas3[i*x + j] = sum;
Добавлено через 4 минуты
Возьми первый вариант, паралелить можно только цикл по i. И как выше сказали, определение временных переменных (c,d,sum) внеси внутрь этого цикла
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
double *proizv(double *mas1, double*mas2, int x) {  //произведение после транспонирования
    double *mas3;
    __m128 *a, *b;
    a = (__m128 *)mas1;
    b = (__m128 *)mas2;
    mas3 = (double *)_mm_malloc(x*x*sizeof(double), 16);
#pragma omp parallel for
    for (int i = 0; i < x; i++) {
        float sum; __m128 c, d;
        for (int j = 0; j < x; j++) {
            d = _mm_set_ps1(0);
            for (int k = 0; k < (x / 4); k++) {
                c = _mm_mul_ps(a[i*x / 4 + k], b[j*x / 4 + k]);
                d = _mm_add_ps(d, c);
            }
            c = _mm_movehl_ps(c, d);
            d = _mm_add_ps(d, c);
            c = _mm_shuffle_ps(d, d, 1);
            d = _mm_add_ss(d, c);
            _mm_store_ss(&sum, d);
            mas3[i*x + j] = sum;
        }
    }
    return mas3;
}
Получилось вот это, время выполнения- 1,5 сек.. Посмотрите, пожалуйста, так должно выглядеть?
Yandex
Объявления
01.06.2016, 10:38     OpenMP и SIMD
Ответ Создать тему
Опции темы

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