Q : Что может быть причиной этого?
... an чрезвычайно низкий (почти ноль) [PARALLEL]
выполнение кода часть
Когда дополнительные дополнения добавляются к пересмотренному Amdahl, «отрицательный» ускорение << 1 </strong> ( замедление ) становятся очевидными
Амдал Закон определяет обоснование ПОЧЕМУ, затем следует ЧТО:
Первое:
никогда не начинать "тестирование" без правильной изоляции SuT - S ystem- u nder- T est, здесь это распределенная -форма вычисление .
Здесь start = time.time()
находится "перед" , оператор import ray
выглядит следующим образом: скорее провокационный тест концентрации читателей на предмете, определенно не признак должным образом спроектированного тестового дизайна - вы сознательно берете в измеренное время также все задержки дискового ввода-вывода + передачи данных с диска в сеанс python, TimeDOMAIN затраты на проверку синтаксиса импортированного модуля, да - интерпретация (не имеющая тех же условий во втором тесте)
Далее:
После сокращения затрат на import
можно начать сравнивать «яблоки с яблоками» :
...
#----------------------------------------- APPLES-TO-APPLES ( STILL AWFULLY NAIVE )
start = time.time()
futures = [ f(i) for i in range(4) ]
print( time.time() - start )
print( 60*"_" + " pure-[SERIAL] python execution" )
#----------------------------------------- ORANGES
start = time.time()
import ray # costs of initial import
ray.init( num_cpus = 4 ) # costs of parametrisation
@ray.remote # costs of decorated def(s)
def f( x ):
return x * x
print( time.time() - start )
print( 60*"_" + " ray add-on overheads" )
#----------------------------------------- APPLES-TO-APPLES ( STILL AWFULLY NAIVE )
start = time.time()
futures = [ f.remote(i) for i in range(4) ]
print( time.time() - start )
print( 60*"_" + " ray.remote-decorated python execution" )
Далее идет масштабирование:
Для миниатюрных масштабов использования , таких как создание всей артиллерии параллельного / распределенного выполнения кода только для вызовов измерения возможны, но искажены многими хитростями, связанными с аппаратным обеспечением и программным обеспечением (распределение памяти и побочные эффекты кэша чаще всего являются блокирующими производительность, после того как SuT был хорошо обработан, чтобы затмить эти очередные типичные проблемы с ядром HP C.
>>> def f( x ):
... return x * x
...
>>> dis.dis( f )
2 0 LOAD_FAST 0 (x)
3 LOAD_FAST 0 (x)
6 BINARY_MULTIPLY
7 RETURN_VALUE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1085 прямо RET
) никогда не будет оправдывать все начальные затраты на настройку и все накладные расходы на дополнительные вызовы, которые имеют значение в случаях небольшой вычислительной плотности, а не в сложных и ресурсоемких вычислительных задачах HP C ( для которого в законе Амдала указано, где находятся основные ограничения для достижения возможного ускорения).
В следующем фрагменте будет показана средняя стоимость одного вызова для f.remote () - звонков, Распределение по 4-CPU ray.remote
-процессам обработки по сравнению с простым монопольным c GIL-пошаговым режимом обработки (подробности о [min, Avg, MAX, StDev] см. в других публикациях по тестированию)
#----------------------------------------- APPLES-TO-APPLES scaled ( STILL NAIVE )
test_4N = 1E6 # 1E6, 1E9, ... larger values may throw exception due to a poor ( not well fused ) range()-iterator construction, workarounds possible
start = time.time()
futures = [ f.remote(i) for i in range( int( test_4N ) ) ]
print( ( time.time() - start ) / test_4N )
print( 60*"_" + " ray.remote-decorated python execution per one call" )
#----------------------------------------- APPLES-TO-APPLES scaled ( STILL NAIVE )
start = time.time()
futures = [ f(i) for i in range( int( test_4N ) ) ]
print( time.time() - start / test_4N )
print( 60*"_" + " pure-[SERIAL] python execution" )
import numpy as np
@ray.remote
def bigSmoke( voidPar = -1 ):
# +------------- this has to compute a lot
# +-------------------------|------------- this has to allocate quite some RAM ~ 130 MB for 100 x str( (2**18)! )
# | | + has to spend add-on overhead costs
# | | for process-to-process result(s) ~ 1.3 MB for (2**18)!
# | | SER/DES-transformations & transfer costs
# | +--------------------|------------- this has to allocate quite some RAM ~ 1.3 MB for (2**18)!
# | | | +- this set with care, soon O/S swapping may occur above physical RAM sizes
return [ str( np.math.factorial( i ) # | and immense degradation of the otherwise CPU-processing appears then
for i in int( 1E2 ) * ( 2**18, )
)
][-1] # <----------------------------- this reduces the amount of SER/DES-transformations & process-2-process transfer costs
...
#----------------------------------------- APPLES-TO-APPLES scaled + computing
test_4N = 1E1 # be cautious here, may start from 1E0, 1E1, 1E2, 1E3 ...
start = time.time()
futures = [ bigSmoke.remote(i) for i in range( int( test_4N ) ) ]
print( ( time.time() - start ) / test_4N )
print( 60*"_" + " ray.remote-decorated set of numpy.math.factorial( 2**18 ) per one call" )
#----------------------------------------- APPLES-TO-APPLES scaled + computing
start = time.time()
futures = [ bigSmoke(i) for i in range( int( test_4N ) ) ]
print( ( time.time() - start ) / test_4N )
print( 60*"_" + " pure-[SERIAL] python execution of a set of numpy.math.factorial( 2**18 ) per one call" )
В любом случае, предупреждаем, что преждевременные усилия по оптимизации могут сбить с толку фокус, поэтому не стесняйтесь читать рассказы о настройке производительности, которые так часто представлены здесь, в StackOverflow.