Почему использование двух задач для выполнения двух длинных вычислений снижает производительность? - PullRequest
0 голосов
/ 26 января 2019

Я делаю программное обеспечение на C # для реализации сжатия RFC 1951 "Deflate".При выборе границ блоков для максимизации сжатия есть возможность вычислить размер двух альтернативных вариантов блоков параллельно, чтобы повысить производительность (это довольно длительное вычисление, включающее вычисление кодов Хаффмана).

Здесьнепараллельная версия:

int bits2 = b2.GetBits();
int bits3 = b3.GetBits();  

Вот параллельная версия:

Task<int> t2 = Task<int>.Factory.StartNew( () => { return b2.GetBits(); } );
int bits3 = b3.GetBits(), bits2 = t2.Result;  

Однако параллельная версия на самом деле работает медленнее, и я не понимаю, почему.В случае, если это актуально, процессор Intel Core i7-6700HQ.Полный код приведен здесь: https://github.com/georgebarwood/pdf/blob/master/Deflator.cs

Почему параллельная версия работает медленнее, чем быстрее, я допустил ошибку и могу ли я что-нибудь сделать, чтобы параллельная версия работала быстрее, чем непараллельная версия?

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Чтобы ответить на мой собственный вопрос: «Что я могу сделать, чтобы параллельная версия работала быстрее, чем непараллельная версия?», Теперь я переработал код для использования двух потоков - 2-й поток выполняет LZ77 сжатие - поиск повторяющихся участков входных данных, которые закодированы как пара (длина-соответствие, расстояние), в то время как основной поток обрабатывает выходные данные каскада LZ77 (генерирует коды Хаффмана, кодирует входные данные с использованием этих кодов).

Это сработало очень хорошо, в целом он работает примерно на 30% быстрее, что очень здорово.

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

Как и прежде, копия кода здесь: https://github.com/georgebarwood/pdf/blob/master/Deflator.cs

0 голосов
/ 26 января 2019

Если я запускаю ваш метод GetBits на моем компьютере, он в среднем работает менее 3 мкс.Параллельный запуск кода имеет некоторые накладные расходы.На самом деле, вызов Task.Factory.StartNew также занимает от 2 до 3 мкс на стороне вызывающей стороны (я не измерял, сколько времени на самом деле начинает выполняться задача).Следовательно, в вашем случае накладные расходы побеждают потенциальную выгоду.

Это одна из трудностей эффективного алгоритма, работающего параллельно: вам необходимо убедиться, что единицы работы достаточно велики, чтобы уравновесить вызванные накладные расходы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...