Как правильно умножить матрицу на другую матрицу в нескольких потоках? Моя задача такая. Мне нужно параллельно на 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()
Код четырех потоков:public static class Thread1 extends Thread @Overrid 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 @Overrid 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 @Overrid 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 @Overrid 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 < b.length; l++) c[i][j] = c[i][j] + a[i][l] * b[l][j]
Алгоритм разделения задачи умножения матриц на несколько потоков следующий:
Делим результат на число потоков. В вашем случае вы хотите использовать 8 потоков, поэтому делим количество строк матрицы A на 8, чтобы получить границы обработки для каждого потока.
Создаем класс потока, где каждый поток будет обрабатывать свой участок результатной матрицы. В вашем случае это заполнение столбцов результирующей матрицы.
В цикле каждый поток пробегается по своей части результатной матрицы, умножая соответствующие элементы соответствующих строк матриц A и B и записывая результат в соответствующий элемент матрицы C.
После завершения всех потоков, собираем результаты в общей результирующей матрице.
Осуществляем синхронизацию потоков, чтобы дождаться их завершения перед объединением результатов в общую матрицу.
Что касается вашего кода, границы циклов в каждом потоке правильно определены для разделения обработки между потоками. Количество циклов зависит от того, как вы разбили обработку. В вашем случае, чтобы умножить матрицу 200x248 на матрицу 248x333 на 8 потоках, вам нужно дополнительно разделить один из измерений на 8, чтобы обеспечить параллелизм.
Алгоритм разделения задачи умножения матриц на несколько потоков следующий:
Делим результат на число потоков. В вашем случае вы хотите использовать 8 потоков, поэтому делим количество строк матрицы A на 8, чтобы получить границы обработки для каждого потока.
Создаем класс потока, где каждый поток будет обрабатывать свой участок результатной матрицы. В вашем случае это заполнение столбцов результирующей матрицы.
В цикле каждый поток пробегается по своей части результатной матрицы, умножая соответствующие элементы соответствующих строк матриц A и B и записывая результат в соответствующий элемент матрицы C.
После завершения всех потоков, собираем результаты в общей результирующей матрице.
Осуществляем синхронизацию потоков, чтобы дождаться их завершения перед объединением результатов в общую матрицу.
Что касается вашего кода, границы циклов в каждом потоке правильно определены для разделения обработки между потоками. Количество циклов зависит от того, как вы разбили обработку. В вашем случае, чтобы умножить матрицу 200x248 на матрицу 248x333 на 8 потоках, вам нужно дополнительно разделить один из измерений на 8, чтобы обеспечить параллелизм.