Zstd: Многопоточный вывод Zstd может зависеть от количества потоков

Созданный на 25 сент. 2020  ·  3Комментарии  ·  Источник: facebook/zstd

Опишите ошибку
Как сообщает @animalize в выпуске № 2238:

При использовании конечной директивы ZSTD_e_end и размера выходного буфера> = ZSTD_compressBound () номер задания рассчитывается функцией ZSTDMT_computeNbJobs (). Эта функция производит разное количество заданий в зависимости от nbWorkers :

https://github.com/facebook/zstd/blob/b706286adbba780006a47ef92df0ad7a785666b6/lib/compress/zstdmt_compress.c#L1243 -L1255

Ожидаемое поведение
Вывод многопоточного сжатия zstd не должен зависеть от количества потоков.

Исправить

  • [] Сделать ZSTDMT_computeNbJobs() независимым от nbWorkers .
  • [] Добавьте фазз-тест, который проверяет, что вывод многопоточного zstd всегда не зависит от количества потоков.

Обходной путь
Если вам нужно обойти эту ошибку, не запускайте потоковую передачу с ZSTD_e_end. Передайте хотя бы один байт ввода с помощью ZSTD_e_continue перед вызовом ZSTD_e_end или убедитесь, что ваш выходной буфер равен < ZSTD_compressBound(inputSize) .

Самый полезный комментарий

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

Да, наверное, проще. Я забыл, что все работы в однопроходном компрессоре MT нужно запускать сразу.

Однажды я хотел предложить добавить функцию ZSTD_compressStream3 (), которая всегда блокирует многопоточное сжатие.

В общем, как люди пишут циклы потокового сжатия, не должно быть ужасно неудобно не добиться максимального прогресса вперед. Если бы мы добавили что-то подобное, для этого не потребовался бы новый API. Вероятно, нам просто нужно добавить параметр сжатия, чтобы управлять им. Но в настоящее время я не вижу в этом большой необходимости.

Все 3 Комментарий

Это ярлык, чтобы сказать, что результат многопоточности zstd не зависит от количества потоков.

Фактически, поддерживаемая функция заключается в том, что результат _streaming_ многопоточности zstd не зависит от количества потоков.
(и это то, что используется zstd CLI).

Это определение позволяет рассмотреть еще одно возможное исправление:
не используйте однопроходный ярлык для ZSTD_e_end когда nbWorkers >= 1 ,
поскольку именно делегирование в однопроходный режим вызывает эту проблему.

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

Другой (потенциально положительный) побочный эффект заключается в том, что он гарантирует, что потоковое многопоточное сжатие _ всегда_ неблокирующее, поскольку оно больше не будет делегировать (блокирующий) однопроходный режим.
_edit_: отказаться от этого, отказ от делегирования в однопроходный режим не гарантирует неблокирующую способность, поскольку при получении директивы ZSTD_e_flush и ZSTD_e_end контракт MT API изменяется с минимального продвижения вперед на максимальный прогресс.

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

Однажды я хотел предложить добавить функцию ZSTD_compressStream3() , которая всегда блокирует многопоточное сжатие.

Если вызывающий продолжает проверять ход неблокирования, это очень неудобно .

edit : Только что нашел, проверка прогресса не очень неудобна:

do {
    zstd_ret = ZSTD_compressStream2(self->cctx, &out, &in, ZSTD_e_continue);
} while (out.pos != out.size && in.pos != in.size && !ZSTD_isError(zstd_ret));

Но лучше иметь всегда блокирующий ZSTD_compressStream3() , это может быть немного быстрее, ИМО многим пользователям-программистам не нужно получать прогресс сжатия.

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

Да, наверное, проще. Я забыл, что все работы в однопроходном компрессоре MT нужно запускать сразу.

Однажды я хотел предложить добавить функцию ZSTD_compressStream3 (), которая всегда блокирует многопоточное сжатие.

В общем, как люди пишут циклы потокового сжатия, не должно быть ужасно неудобно не добиться максимального прогресса вперед. Если бы мы добавили что-то подобное, для этого не потребовался бы новый API. Вероятно, нам просто нужно добавить параметр сжатия, чтобы управлять им. Но в настоящее время я не вижу в этом большой необходимости.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги