Многопоточность Python читает буфер памяти только для чтения GIL

У меня есть много файлов на диске, которые нужно прочитать, 1-й вариант - использовать многопоточность, он очень хорошо работает на SSD. (когда потоки заблокированы IO, он выпустит GIL)

Но я хочу достичь такой же или более высокой скорости без SSD, поэтому я предварительно загружаю их в память (например, сохраняю в dict), и каждый поток будет читать содержимое каждого файла из памяти. К сожалению, возможно из-за GIL, в dict есть блокировка, следовательно, его скорость даже медленнее, чем загрузка файлов с SSD!

Так что мой вопрос заключается в том, что есть какое-либо решение может создать буфер памяти только для чтения без блокировки /GIL? как ramdisk или что-то еще>

2 ответа

Короче нет.

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

(Отдельное спасибо Грэму Дамплтону!) Одним из решений является написание C-расширений для CPython. И отпустите GIL, когда войдете в "царство C". Только будьте осторожны, что вы не можете получить доступ к содержимому Python без защиты GIL, иначе это вызовет незначительные ошибки или произойдет сбой напрямую.

Есть несколько реализаций, которые не используют GIL, например, Jython и Cython (не CPython). Вы можете попробовать использовать их. Но имейте в виду, что написать правильную многопоточную программу сложно. Написание быстрой многопоточной программы еще сложнее. Я предлагаю написать многопроцессорную программу вместо многопоточности. И передавать данные через IPC или около того (скажем, ZeroMQ, это простой в использовании и легкий).

Позвольте мне добавить несколько моментов к ответу @HKTonyLee.

Так что у Python есть этот GIL. Но он освобождается при выполнении, например, файлового ввода-вывода. Это означает, что вы можете параллельно читать файлы. Поскольку с точки зрения процессов нет такой вещи, как файл, а есть только файловые дескрипторы (при условии posix), поэтому все, что вы читаете, не должно храниться на диске.

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

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