-30 / 13 / 1
Регистрация: 18.12.2018
Сообщений: 422
1

Как разделить на два потока умножение матрицы?

01.03.2020, 01:00. Показов 2067. Ответов 3

Составил алгоритм умножения матриц, однако не совсем могу понять, какие задать параметры для функции MultMatrixThread, чтобы программа работала параллельно:
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include<iostream>
#include<stdio.h>
#include<Windows.h>
#include<thread>
 
using namespace std;
 
//заполнение матрицы
void FillMatrix(int *Matrix[], int nRow, int nCol)
{
    for (int i = 0; i < nRow; i++)
    {
        for (int j = 0; j < nCol; j++)
        {
            Matrix[i][j] = rand() % 20;
        }
    }
}
 
void ShowMatrix(int *Matrix[], int nRow, int nCol)
{
    for (int i = 0; i < nRow; i++)
    {
        for (int j = 0; j < nCol; j++)
        {
            cout << Matrix[i][j] << " ";
        }
        cout << endl;
    }
}
 
//Функция умножения матрицы
void MultMatrix(int *C_arr[], int *A_arr[], int *B_arr[], int Arow, int Bcol, int Acol)
{
    for (int i = 0; i < Arow; i++)
    {
        for (int j = 0; j < Bcol; j++)
        {
            C_arr[i][j] = 0;
            for (int k = 0; k < Acol; k++)
                C_arr[i][j] += A_arr[i][k] * B_arr[k][j];
        }
    }
}
 
//Параллельная функция
void MultMatrixThread(int *C_arr[], int *A_arr[], int *B_arr[],
    int ArowStart, int BcolStart,
    int Arow, int Bcol, int Acol)
{
    for (int i = ArowStart; i < Arow; i++)
    {
        for (int j = BcolStart; j < Bcol; j++)
        {
            C_arr[i][j] = 0;
            for (int k = 0; k < Acol; k++)
                C_arr[i][j] += A_arr[i][k] * B_arr[k][j];
        }
    }
}
 
 
//входная функция
int main()
{
    setlocale(LC_ALL, "ru");
    int st1, en1, st2, en2; //время выполнения
    int Arow, Acol, Brow, Bcol;
    cout << "Столбцы матрицы A должны совпадать со строками матрицы B\n";
    cout << "Cтроки матрицы A: ";
    //cin >> Arow;
    Arow = 300;
    cout << "Столбцы матрицы A: ";
    //cin >> Acol;
    Acol = 100;
    cout << "Cтроки матрицы B: ";
    //cin >> Brow;
    Brow = 100;
    cout << "Столбцы матрицы B: ";
    //cin >> Bcol;
    Bcol = 200;
    int **A_arr = new int*[Arow];
    int **B_arr = new int*[Brow];
    if (Acol != Brow)
    {
        cout << "Умножение невозможно!";
        return 0;
    }
 
    //строки матрицы A
    for (int i = 0; i < Arow; i++)
        A_arr[i] = new int[Acol];
 
    //строки матрицы B
    for (int i = 0; i < Brow; i++)
        B_arr[i] = new int[Bcol];
 
    FillMatrix(A_arr, Arow, Acol);
    FillMatrix(B_arr, Brow, Bcol);
 
    printf("\nМатрица A\n");
    //ShowMatrix(A_arr, Arow, Acol);
    printf("\nМатрица B\n");
    //ShowMatrix(B_arr, Brow, Bcol);
 
    //Формируем матрицу C
    int **C_arr_main = new int*[Arow];
    for (int i = 0; i < Arow; i++)
    {
        C_arr_main[i] = new int[Bcol];
    }
 
    st1 = GetTickCount();
    MultMatrix(C_arr_main, A_arr, B_arr, Arow, Bcol, Acol);
    en1 = GetTickCount();
    printf("\nМатрица C\n");
    //ShowMatrix(C_arr, Arow, Bcol);
    printf("\nОдин поток: %d ms ", en1 - st1);
 
    //2 потока
    int **C_arr_2Thr = new int*[Arow];
    for (int i = 0; i < Arow; i++)
    {
        C_arr_2Thr[i] = new int[Bcol];
    }
    
        //1 поток
    thread thr1(MultMatrixThread, C_arr_2Thr, A_arr, B_arr,
        0,0,
        Arow / 2, Bcol / 2, Acol);
        //2 поток
    thread thr2(MultMatrixThread, C_arr_2Thr, A_arr, B_arr,
        Arow / 2 + 1, Bcol / 2 + 1,
        Arow, Bcol, Acol);
 
    //////////////////////////
    ////ОСВОБОЖДАЕМ ПАМЯТЬ////
    for (int i = 0; i < Arow; i++)
        delete A_arr[i];
 
    for (int i = 0; i < Brow; i++)
        delete[] B_arr[i];
 
    for (int i = 0; i < Arow; i++)
        delete[] C_arr_main;
 
    for (int i = 0; i < Arow; i++)
        delete[] C_arr_2Thr;
 
    delete[] A_arr;
    delete[] B_arr;
    delete[] C_arr_main;
    delete[] C_arr_2Thr;
    return 0;
}
То есть, если умножение матриц А и В само по себе является умножением строк матрицы А на столбцы В, то при двух потоках можно будет перемножать просто половины количества строк А на половину столбцов В.
Но у меня не совсем получается понять, как будет формироваться результирующая матрица C_arr_2Thr, если программа работает при двух потоках?
Причем компилятор у меня как раз и ругается на эту строку:
C++
1
2
3
            C_arr[i][j] = 0;
            for (int k = 0; k < Acol; k++)
                C_arr[i][j] += A_arr[i][k] * B_arr[k][j];
Миниатюры
Как разделить на два потока умножение матрицы?  
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.03.2020, 01:00
Ответы с готовыми решениями:

Как разделить два потока аудио?
Приветствую! Прошу прощения если на форуме уже есть такая тема (ткните носом если есть), но я не...

Задать два числа как два массива и потом выполнить сложение, умножение и деление
Здравствуйте! Суть задачи в следующем: Нужно задать два числа как два массива и потом выполнить...

Как разделить звук на 2 потока?
Привет всем, у меня такая просьба о помощи, у меня hdmi то есть все ровно, но не как не могу...

Два потока, две очереди, два потока
Есть две очереди. Каждая из них заполняется своим потоком. Есть два потока, которые достают данные...

3
5233 / 2887 / 1208
Регистрация: 07.02.2019
Сообщений: 7,285
01.03.2020, 02:12 2
SalavatGood,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Параллельная функция
void MultMatrixThread(int *C_arr[], int *A_arr[], int *B_arr[],
    int ArowStart, int rowCount, int Bcol, int Acol)
{
    for (int i = ArowStart; i < ArowStart + rowCount; i++)
    {
        for (int j = 0; j < Bcol; j++)
        {
            C_arr[i][j] = 0;
            for (int k = 0; k < Acol; k++)
                C_arr[i][j] += A_arr[i][k] * B_arr[k][j];
        }
    }
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//...
    st1 = GetTickCount();
    MultMatrix(C_arr_main, A_arr, B_arr, Arow, Bcol, Acol);
    en1 = GetTickCount();
    printf("\nОдин поток: %d ms ", en1 - st1);
 
    //2 потока
    //1 поток
    st1 = GetTickCount();
    thread thr1(MultMatrixThread, C_arr_main, A_arr, B_arr,
        0, Arow / 2, Bcol, Acol);
    //2 поток
    thread thr2(MultMatrixThread, C_arr_main, A_arr, B_arr,
        Arow / 2, Arow / 2 + Arow % 2, Bcol, Acol);
 
    thr1.join();
    thr2.join();
 
    en1 = GetTickCount();
    printf("\nДва потока: %d ms ", en1 - st1);
//...
1
-30 / 13 / 1
Регистрация: 18.12.2018
Сообщений: 422
01.03.2020, 12:27  [ТС] 3
zayats80888, спасибо, только не совсем понятно с этой строкой:
C++
1
 Arow / 2, Arow / 2 + Arow % 2, Bcol, Acol);
Arow%2 же равно 0, то есть на втором потоке мы ничего же не параллелим, разве не так?
0
5233 / 2887 / 1208
Регистрация: 07.02.2019
Сообщений: 7,285
01.03.2020, 18:39 4
Лучший ответ Сообщение было отмечено SalavatGood как решение

Решение

Цитата Сообщение от SalavatGood Посмотреть сообщение
Arow%2 же равно 0, то есть на втором потоке мы ничего же не параллелим, разве не так?
Arow % 2 учитывает нечетное количество строк.
Смотрим сигнатуру:
C++
1
2
void MultMatrixThread(int *C_arr[], int *A_arr[], int *B_arr[],
    int ArowStart, int rowCount, int Bcol, int Acol)
У тебя Arow = 300.
Значит цикл for (int i = ArowStart; i < ArowStart + rowCount; i++) раскрывается
для первого потока:
C++
1
2
3
4
5
6
thread thr1(MultMatrixThread, C_arr_main, A_arr, B_arr,
        0, Arow / 2, Bcol, Acol);
 
// ArowStart = 0
// rowCount = 300 / 2 = 150
// for (int i = 0; i < 0 + 150; i++) --> for (int i = 0; i < 150; i++)
для второго потока:
C++
1
2
3
4
5
6
thread thr2(MultMatrixThread, C_arr_main, A_arr, B_arr,
        Arow / 2, Arow / 2 + Arow % 2, Bcol, Acol);
 
// ArowStart = 300 / 2 = 150
// rowCount = 300 / 2  + 300 % 2 = 150
// for (int i = 150; i < 150 + 150; i++) --> for (int i = 150; i < 300; i++)
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.03.2020, 18:39
Помогаю со студенческими работами здесь

Если максимум и минимум матрицы чётные, то разделить их на два, иначе поменять местами первый и предпоследний столбец
Ввести целочисленный двумерный массив A(NxM), вывести его. Если максимум и минимум массива...

Как разделить строку по два символа
Как разделить получаемую строку по два символа Допустим ввожу С645 нужно разделить на С6 и 45 и...

Как правильно разделить два числа
Подскажите пожалуйста, как правильно разделить два числа на ассемблере(TASM)! Возник спор с...

Как разделить столбец на два столбца?
Как разделить столбец на два столбца?

Как разделить диск на два раздела?
Как это можно сделать? вроде разбил, но при установке пишет что partition один. После установки...

Как создать два потока
Как создать два потока в оконном приложении??


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru