Умножение матрицы Java: потоковое медленнее, чем непоточное в случае маленьких столбцов

Я тестирую программу точечного продукта на Java с многопоточными (в зависимости от количества ядер системы) и непоточными вариантами. (Очень простой) алгоритм делит первую (скажем, A) матрицу на столько матриц, сколько ядер, и выполняет скалярное произведение с полной матрицей B. Как только это будет сделано, собираются «фрагменты» с получением результирующей матрицы. Когда строки и столбцы имеют относительно высокий размер (скажем, 20000 строк и 20000 столбцов), то многопоточный вариант работает должным образом, обеспечивая скорость в 3,3–3,5 раза выше, чем непоточный вариант со стандартной четырехъядерной системой.

Но для небольшого количества столбцов в первой матрице (например, A [20000] [20], умноженного на B [20] [20000]) скорости для потоковых и непоточных вариантов примерно равны. А для меньшего количества столбцов время выполнения в многопоточном режиме заметно выше, чем при непоточном варианте. Эта «граница равенства» варьируется в зависимости от количества строк.

Я понимаю проблемы с системой перегруженных потоков для маленьких матриц, но я не могу полностью понять эту ситуацию только при небольшом количестве столбцов (столбцы в первом матричном множителе, строки во втором). Если проблема имеет ту же природу, что и проблема небольших матриц, существует ли соотношение между строками и столбцами, которое позволяет выбирать поточный или непоточный алгоритм в зависимости от случая?

Если вы спрашиваете о проблеме с кодом, отправьте сообщение минимальный воспроизводимый пример

Erwin Bolwidt 22.07.2018 13:32

Спасибо за комментарий, Эрвин. Я принимаю к сведению будущие запросы.

A. Isasa 22.07.2018 15:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
2
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Создание нового потока всегда требует (примерно постоянного) количества вычислительного времени, и, прежде чем ваша программа сможет извлечь из этого выгоду, работа над потоком должна занять больше времени, чем эти накладные расходы. Я не знаю, как вы кодируете (пожалуйста, опубликуйте минимальные примеры в будущем, например, предложенный комментарий), но вы можете посмотреть количество вычислений (умножение + сложение), которые каждый поток оценивает за одинаковое время расчета. Исходя из этого, вы сможете приблизительно определить размер матрицы (вероятно, пропорциональной произведению длин сторон = количеству элементов), где многопоточность стоит проблем.

Большое спасибо за ваш комментарий и ваше время. Мой вопрос был скорее концептуальным, чем практическим (извиняюсь перед всеми за это), но ваш ответ дает мне подсказки для продолжения исследования количества операций (мультипликации и добавлений) в каждом потоке. Конечно, существует прямая связь между количеством элементов и эффективностью потока, но когда мы обнаруживаем небольшое количество столбцов в первом множителе, мы тогда работаем с большим количеством умножений и небольшим количеством добавлений, не говоря уже о самом различный вывод приводит к размеру матрицы продукта. Еще раз спасибо.

A. Isasa 22.07.2018 15:39

@ A.Isasa Я предлагаю вам повторно использовать пул потоков, такой как пул потоков, используемый Stream.parallel ()

Peter Lawrey 22.07.2018 22:10

@PeterLawrey Спасибо, Питер. Я пробовал более «классическое» решение с потоками, но я дам возможность Stream API как более новое (ну, Java 8, со временем ...) решение. Большое спасибо!

A. Isasa 22.07.2018 22:52

@ A.Isasa Я считаю IntStream.range (0, a.length) .parallel () и т.д. очень полезным.

Peter Lawrey 23.07.2018 08:44

Другие вопросы по теме