Re: параллельность + синхронизации (примеры)
Добавлено: 14 дек 2014, 20:34
Ну а теперь - параллельные процессы, но реализуемые пакетом multiprocessing в виде класса Process.Olej писал(а): Это сделано, пока, специально на fork(), так что под Windows такое не покатит
Родительский процесс синхронизирует порождённые по времени ("пора заканчивать") сигналом UNIX SIGUSR1, а данные обратно возвращаются через массив в shared memory.
Это сработает в любой OS.
Меня просто удивляет, насколько изощрённо реализован пакет multiprocessing в Python ... хоть в общих чертах и понятно что и как они делают (при отсутствии клонирования fork() во всём, что a'la Windows!): запускают как клон уже загруженную копию Python с выполняющимся приложением ... но сделано это мастерски.
Код: Выделить всё
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import time
import sys
import signal
import math
import multiprocessing
# параллельные процессы - все OS:
def handler( signum, frame ): # обработчик SIGUSR1
global finish
finish = True
def RunCounter( arr, num ) :
global finish
signal.signal( signal.SIGUSR1, handler )
counter = 0
while not finish : counter += 1
arr[ num ] = counter
if __name__ == '__main__' : # для работы в Windows
multiprocessing.freeze_support()
nthr = 2 # число процессов
sec = 1 # интервал выполнения
debug = False
finish = False # флаг завергшения
try :
if len( sys.argv ) > 1 :
nthr = int( sys.argv[ 1 ] )
if len( sys.argv ) > 2 :
sec = int( sys.argv[ 2 ] )
if sec < 0 : # признак отладочной диагностики
sec = -sec
debug = True
except ValueError :
print( 'запуск: python[3] {} [потоков] [[-]секунд]'.format( sys.argv[ 0 ] ) )
sys.exit( 1 )
if( debug ) :
print( 'число процессов {}'.format( nthr ) )
print( 'число доступных процессоров {}'.format( multiprocessing.cpu_count() ) )
counter = 0
childs = []
res = multiprocessing.Array( 'i', range( nthr ) ) # массив результатов в shared memory
for i in range( nthr ) : # создание и запуск процессов
p = multiprocessing.Process( target=RunCounter, args=( res, i ) )
childs.append( p )
p.start()
time.sleep( sec )
for p in childs : os.kill( p.pid, signal.SIGUSR1 )
for p in childs : p.join()
if debug :
msg = ''
for i in range( len( res ) ) : msg += '{} '.format( res[ i ] )
print( '{}'.format( msg ) )
sum1, sum2, sq, md = 0.0, 0.0, 0.0, 0.0 # сбор статистики
for i in range( len( res ) ) :
md = float( res[ i ] )
sum1 += md
sum2 += md * md;
md = sum1 / nthr; # среднее
sq = math.sqrt( sum2 / nthr - md * md ); # СКО
print( 'операций {:.0f} : {} * {:.0f} [+/-{:.2f}%]'
.format( sum1 , nthr, md, 100. * sq / md ) )
sys.exit( 0 )
Код: Выделить всё
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 1 3
операций 62905291 : 1 * 62905291 [+/-0.00%]
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 2 3
операций 113488958 : 2 * 56744479 [+/-0.05%]
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 3 3
операций 147101944 : 3 * 49033981 [+/-9.55%]
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 4 3
операций 164361496 : 4 * 41090374 [+/-2.41%]
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 5 3
операций 175403773 : 5 * 35080755 [+/-2.18%]
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 10 3
операций 167149453 : 10 * 16714945 [+/-2.94%]
[Olej@modules SpeedThread.6]$ ./PymSpeed.py 50 3
операций 187893503 : 50 * 3757870 [+/-5.40%]