Как правильно умножить матрицу на другую матрицу в нескольких потоках? Моя задача такая. Мне нужно параллельно на 8 потоках умножить матрицу 200x248 на матрицу 248x333. В интернете я нашел простой пример умножения двух матриц 4x4 на 4 потоках, но я не совсем понимаю логику разделения этой задачи между потоками. Почему у каждого потока разные границы циклов и как они вообще образовываются? Почему в каждом потоке аж 3 цикла, а не 2? Можете мне объяснить алгоритм, чтобы я мог по его аналогии сделать умножение огромных матриц на 8 потоках?
Вот часть этого кода (там еще есть ввод данных с файла и вывод результата в другой файл, графический интерфейс и другое, но это не столь важно в этом вопросе).
Инициализация статических полей:public static int[][] a;
public static int[][] b;
public static int[][] c;
Где-то в main создаются и запускаются потоки:c = new int[a.length][b[0].length];
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
Thread3 thread3 = new Thread3();
Thread4 thread4 = new Thread4();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
thread3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
thread4.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Код четырех потоков:public static class Thread1 extends Thread {
@Override
public void run() {
int m = a.length;
int n = b[0].length;
int k = (a.length) / 4;
for (int i = 0; i <= k; i++) {
for (int j = 0; j < n; j++) {
for (int l = 0; l < b.length; l++) {
c[i][j] = c[i][j] + a[i][l] * b[l][j];
}
}
}
}
}
public static class Thread2 extends Thread {
@Override
public void run() {
int m = a.length;
int n = b[0].length;
int k = (a.length) / 2 + 1;
int s = ((a.length) / 4) + 1;
for (int i = s; i < k; i++) {
for (int j = 0; j < n; j++) {
for (int l = 0; l < b.length; l++) {
c[i][j] = c[i][j] + a[i][l] * b[l][j];
}
}
}
}
}
public static class Thread3 extends Thread {
@Override
public void run() {
int m = a.length;
int n = b[0].length;
int k = ((3 * (a.length)) / 4) + 1;
int s = (a.length) / 2 + 1;
for (int i = s; i < k; i++) {
for (int j = 0; j < n; j++) {
for (int l = 0; l < b.length; l++) {
c[i][j] = c[i][j] + a[i][l] * b[l][j];
}
}
}
}
}
public static class Thread4 extends Thread {
@Override
public void run() {
int m = a.length;
int n = b[0].length;
int k = ((3 * (a.length)) / 4) + 1;
for (int i = k; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int l = 0; l

21 Авг 2019 в 06:11
208 +1
0
Ответы
1

Алгоритм разделения задачи умножения матриц на несколько потоков следующий:

Делим результат на число потоков. В вашем случае вы хотите использовать 8 потоков, поэтому делим количество строк матрицы A на 8, чтобы получить границы обработки для каждого потока.

Создаем класс потока, где каждый поток будет обрабатывать свой участок результатной матрицы. В вашем случае это заполнение столбцов результирующей матрицы.

В цикле каждый поток пробегается по своей части результатной матрицы, умножая соответствующие элементы соответствующих строк матриц A и B и записывая результат в соответствующий элемент матрицы C.

После завершения всех потоков, собираем результаты в общей результирующей матрице.

Осуществляем синхронизацию потоков, чтобы дождаться их завершения перед объединением результатов в общую матрицу.

Что касается вашего кода, границы циклов в каждом потоке правильно определены для разделения обработки между потоками. Количество циклов зависит от того, как вы разбили обработку. В вашем случае, чтобы умножить матрицу 200x248 на матрицу 248x333 на 8 потоках, вам нужно дополнительно разделить один из измерений на 8, чтобы обеспечить параллелизм.

20 Апр 2024 в 13:22
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир