Из документации Numba:
Экспериментальная параллельная = True опция @jit попытается оптимизировать операции с массивами и запустить их параллельно. Также добавлена поддержка prange () для явного распараллеливания цикла.
Теперь, поскольку вы не выполняете никаких операций с массивами в своей функции, Numba не может ничего распараллелить без явного пометки циклов с помощью prange.
Так что просто чтобы убедиться, что нет путаницы.
Numba будет разбивать ваш цикл на потоки только тогда, когда вы установите параллельное = True в декорации, и явно помечает циклы, изменяя их; диапазон -> prange.
В вашей функции f4 () вы поместили prange на все циклы for, я бы рекомендовал помещать prange только в самый внешний цикл, потому что вы не хотите рисковать порождением потоков из потоков.
I.e.:
@njit(parallel=True)
def f5(n):
s = 0
for i in prange(n):
for j in range(n):
for k in range(n):
s += (i * k < j * j) - (i * k > j * j)
return s