Как отключить предупреждение TOKENIZERS_PARALLELISM=(true | false)?
Я использую pytorch для обучения модели huggingface-transformers, но каждую эпоху всегда выводил предупреждение:
The current process just got forked. Disabling parallelism to avoid deadlocks... To disable this warning, please explicitly set TOKENIZERS_PARALLELISM=(true | false)
Как отключить это предупреждение?
5 ответов
Установите переменную среды в строку "false"
либо по
TOKENIZERS_PARALLELISM=false
в твоей оболочке
или по:
import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"
в скрипте Python
Я собираюсь оставить этот комментарий здесь, чтобы помочь всем, кто задается вопросом, можно ли сохранить параллелизм и сэкономить драгоценное время во время обучения. А также потому, что это первая страница stackoverflow при поиске ошибки непосредственно в Google.
Согласно этому комментарию на github,проблема заключается в FastTokenizers . Также, согласно другому комментарию к gitmemory, вы не должны использовать токенизатор перед разветвлением процесса. (что в основном означает перед повторением загрузчика данных)
Таким образом, решение состоит в том, чтобы не использовать FastTokenizer перед обучением / тонкой настройкой или использовать обычные токенизаторы.
Проверьте документацию по huggingface, чтобы узнать, действительно ли вам нужен FastTokenizer.
Если вы явно выбрали быстрые (код Rust) токенизаторы, возможно, вы сделали это не просто так. При работе с большими наборами данных токенизаторы на основе Rust обрабатывают данные намного быстрее, и их можно явно вызвать, установив параметр «use_fast» во время создания токенизатора. В настоящее время почти все модели HF поставляются с этой опцией. Хотя это и не очевидно из предупреждающего сообщения, TOKENIZERS_PARALLELISM является переменной env, а не гиперпараметром токенизатора. Если установить для этого параметра значение False, проблема действительно исчезнет, но, как показывают некоторые из приведенных выше комментариев, возникает путаница в отношении влияния этого изменения. Например, влияет ли это на параллелизм на уровне модели? Давайте посмотрим на код Rust, чтобы увидеть, каково поведение по умолчанию и что может произойти, если мы отключим его, чтобы решить проблему.
https://docs.rs/tokenizers/latest/src/tokenizers/utils/parallelism.rs.html В большинстве случаев мы (конечный пользователь) не устанавливали бы явно для TOKENIZERS_PARALLELISM значение True или False. Во всех таких случаях код токенизатора предполагает, что это значение TRUE. Мы можем явно отключить его, установив для него значение False. Но вы можете видеть, что в этом случае код делает итератор сериализованным. Даже если вы не установите для этой переменной env значение False, исполняемый код сделает это сам, если позже встретится с форками Python (и именно это приводит к отображению предупреждения в первую очередь). Можем ли мы этого избежать?
Вернемся к самому предупреждению.
"Текущий процесс только что разветвился после того, как параллелизм уже использовался. Отключение параллелизма во избежание взаимоблокировок... Чтобы отключить это предупреждение, вы можете: - Избегать использованияtokenizers
перед разветвлением, если это возможно - Явно установите переменную среды TOKENIZERS_PARALLELISM=(true | false)"
Это происходит только с FastTokenizers HF, поскольку они выполняют параллельную обработку в Rust. В этой ситуации, когда мы разветвляем процессы через многопроцессорность в Python, возникает конфликт. Разветвление происходит потому, что мы начали бы зацикливаться на загрузчике данных (с num_workers>0) в методе train(). Эта комбинация считается небезопасной для работы, и если она встречается, токенизатор сам отключает параллелизм, чтобы избежать взаимоблокировок. Когда мы говорим здесь о параллелизме, мы строго имеем в виду код токенизатора, а НЕ что-то еще. Другими словами, затрагиваются только те части кода, где мы конвертируем входные текстовые данные в токены (скажем, с помощью tokenizer.encode_plus или любой другой функции). Таким образом, это не должно влиять на использование параллельных потоков с num_workers, которые используют несколько ядер графического процессора... например, функцию загрузки данных. Как мы можем это сказать? Что ж, мы можем просто попробовать добавить 5-секундную задержку в функцию get_item набора данных вместе с оператором печати, а затем убедиться в этом сами, перебирая загрузчик данных в цикле для значений diff num_workers. Когда num_workers = 0, основной процесс выполняет тяжелую работу, и между выборками есть промежуток в 5 секунд. Когда num_workers = 1 происходит форк, мы получаем указанное выше предупреждение о параллелизме, и, поскольку основной процесс не участвует в подъеме данных, мы все равно получаем 5-секундный промежуток между выборками. Начиная с num_workers > 2, выполняется несколько выборок в зависимости от num_workers с интервалом в 5 секунд. основной процесс выполняет тяжелую работу, и между выборками есть промежуток в 5 секунд. Когда num_workers = 1 происходит форк, мы получаем указанное выше предупреждение о параллелизме, и, поскольку основной процесс не участвует в подъеме данных, мы все равно получаем 5-секундный промежуток между выборками. Начиная с num_workers > 2, выполняется несколько выборок в зависимости от num_workers с интервалом в 5 секунд. основной процесс выполняет тяжелую работу, и между выборками есть промежуток в 5 секунд. Когда num_workers = 1 происходит форк, мы получаем указанное выше предупреждение о параллелизме, и, поскольку основной процесс не участвует в подъеме данных, мы все равно получаем 5-секундный промежуток между выборками. Начиная с num_workers > 2, выполняется несколько выборок в зависимости от num_workers с интервалом в 5 секунд.
На самом деле это приводит к выводу, что простым вариантом исправления приведенного выше предупреждения может быть просто установка num_workers = 0 в определении загрузчика данных. Если num_workers равно 0, то вилки Python нет, и основной процесс сам выполняет всю работу по подъему данных. Это работает, и теперь мы можем максимально использовать возможности быстрых токенизаторов, но за счет устранения параллельной обработки на стороне Python. Учитывая, что загрузчики данных лучше всего работают в параллельном режиме, предварительно загружая пакеты параллельно с GPU с хоста (ЦП) для выполнения, это обычно НЕ является хорошим вариантом.
Что произойдет, если мы установим TOKENIZERS_PARALLELISM=true? В последних версиях Pytorch, трансформаторов, токенизаторов и т. д., если вы сделаете это, а затем попробуете тренироваться с num_workers>0 в загрузчике данных, ваше обучение зависнет без каких-либо ошибок или даже предупреждающих сообщений. Фактически, эта проблема побудила меня опубликовать этот ответ, поскольку я нигде не мог найти решение, чтобы исправить эту проблему с зависанием обучения. Основной причиной на самом деле является загрузчик данных, который в этой ситуации дает сбой из-за вышеупомянутого конфликта (он отказывается «разветвляться» из-за боязни взаимоблокировок).
Итак, возвращаясь к нашей основной проблеме, кажется, что параллелизм на основе RUST противоречит форкам, которые мы делаем в Python. Однако это можно легко решить, просто удалив все использование токенизаторов перед обучающим вызовом (т. е. до использования загрузчика данных). Много раз мы можем использовать токенизаторы, чтобы увидеть, что представляет собой токенизированный вывод и т. д., выполнив my_dataset_name[0]. Просто удалите все такие вызовы токенизатора и позвольте циклу функции train() быть первым, когда доступ к токенизатору будет получен. Это простое исправление заставляет пареллизацию RUST происходить после форка Python, и это должно работать.
В качестве альтернативы заранее преобразуйте свои данные в токены и сохраните их в dict. Тогда ваш набор данных вообще не должен использовать токенизатор, а во время выполнения просто вызывает dict(key), где ключ является индексом. Так вы избежите конфликта. Предупреждение все еще появляется, но вы просто больше не используете токенизатор во время обучения (обратите внимание на такие сценарии, чтобы сэкономить место, избегайте заполнения во время токенизации и добавляйте позже с помощью collate_fn)
Сказав все это, реализация токенизатора Rust настолько безумно быстра, что обычно не имеет значения, даже если сериализованная опция вызывается внутри токенизатора, то есть если параллелизм автоматически отключается в токенизаторе. Он по-прежнему превосходит обычный токенизатор.
Таким образом, в большинстве случаев можно просто проигнорировать предупреждение и отключить распараллеливание токенизатора во время выполнения... или явно установить для TOKENIZERS_PARALLELISM значение False с самого начала. В редких случаях, когда скорость имеет первостепенное значение, можно изучить один из предложенных выше вариантов.
Я решил эту проблему, понижая huggingface в трансформаторах для версии библиотеки от 3.0.0 до 2.11.0 и tokenizers версии библиотеки от 0.8.0rc4 до 0.7.0.
Похоже, это проблема версии библиотеки токенизатора huggingface "0.8.0rc4". В настоящее время кажется, что нет решения для установки TOKENIZERS_PARALLELISM=(true | false), как говорится в сообщении об ошибке.
ссылка: https://github.com/ThilinaRajapakse/simpletransformers/issues/515
Установите для переменной среды строку «false»:
- На Баше
export TOKENIZERS_PARALLELISM=false
- На Python
import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"