Опишите ошибку
Как сообщает @animalize в выпуске № 2238:
При использовании конечной директивы ZSTD_e_end и размера выходного буфера> = ZSTD_compressBound () номер задания рассчитывается функцией ZSTDMT_computeNbJobs (). Эта функция производит разное количество заданий в зависимости от nbWorkers
:
Ожидаемое поведение
Вывод многопоточного сжатия zstd не должен зависеть от количества потоков.
Исправить
ZSTDMT_computeNbJobs()
независимым от nbWorkers
.Обходной путь
Если вам нужно обойти эту ошибку, не запускайте потоковую передачу с ZSTD_e_end. Передайте хотя бы один байт ввода с помощью ZSTD_e_continue перед вызовом ZSTD_e_end или убедитесь, что ваш выходной буфер равен < ZSTD_compressBound(inputSize)
.
Это ярлык, чтобы сказать, что результат многопоточности 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. Вероятно, нам просто нужно добавить параметр сжатия, чтобы управлять им. Но в настоящее время я не вижу в этом большой необходимости.
Самый полезный комментарий
Да, наверное, проще. Я забыл, что все работы в однопроходном компрессоре MT нужно запускать сразу.
В общем, как люди пишут циклы потокового сжатия, не должно быть ужасно неудобно не добиться максимального прогресса вперед. Если бы мы добавили что-то подобное, для этого не потребовался бы новый API. Вероятно, нам просто нужно добавить параметр сжатия, чтобы управлять им. Но в настоящее время я не вижу в этом большой необходимости.