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

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

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

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


person user2497340    schedule 01.11.2016    source источник
comment
Если вам действительно нужна максимальная скорость, как насчет того, чтобы переписать вашу программу (или, по крайней мере, ее критичные для скорости части) на C или C++ или на каком-либо другом полностью компилируемом языке? Тогда у вас не будет GIL, а также вообще никаких накладных расходов на интерпретатор, поскольку вы будете запускать собственный исполняемый файл.   -  person Jeremy Friesner    schedule 01.11.2016


Ответы (2)


Короче говоря, нет.

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

(Отдельное спасибо Грэму Дамплтону!) ?noredirect=1#comment67962758_40354355">решение состоит в том, чтобы написать расширения C для CPython. И отпустите GIL, когда войдете в «царство C». Просто будьте осторожны, чтобы вы не могли получить доступ к материалам Python без защиты GIL, иначе это вызовет тонкие ошибки или прямой сбой.

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

person HKTonyLee    schedule 01.11.2016
comment
Не совсем. Поскольку потоки C используются в CPython под прикрытием, то технически несколько потоков все еще могут работать, но только один из них может одновременно запускать код Python. Такая тонкая разница с тем, что вы описываете. Используя расширения C для CPython, если данные, с которыми им нужно работать, не требуют блокировки глобального интерпретатора Python для объектов данных Python, тогда несколько потоков могут успешно выполняться одновременно. - person Graham Dumpleton; 01.11.2016

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

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

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

person freakish    schedule 16.11.2016
comment
к сожалению, GIL невероятно плох, чем больше у вас потоков, которые работают с процессором, тем медленнее будет чтение ввода-вывода, например, в сокетах UDP, и он начнет отбрасывать пакеты... - person Enerccio; 13.08.2018