В некоторых случаях приложение может не использовать даже одно ядро полностью, и использование потоков (или процессов) может помочь в этом.
Подумайте о типичном веб-приложении.Он получает запросы от клиентов, выполняет некоторые запросы к базе данных и возвращает данные обратно клиенту.Учитывая, что операция ввода-вывода на порядок медленнее, чем работа процессора, большую часть времени такое приложение ожидает завершения ввода-вывода.Сначала он ожидает чтения запроса из сокета.Затем он ожидает, пока запрос к базе данных не будет записан в сокет, открытый для БД.Затем он ожидает ответа от базы данных, а затем пишет ответ в сокет клиента.
Ожидание завершения ввода-вывода может занять 90% (или более) времени обработки запроса.Когда однопоточное приложение ожидает ввода-вывода, оно просто не использует ядро, а ядро доступно для выполнения.Поэтому в таком приложении есть место для выполнения другими потоками даже на одном ядре.
В этом случае, когда один поток ожидает завершения ввода-вывода, он освобождает GIL, а другой поток может продолжить выполнение.