Lors de la résolution du puzzle de code sur un certain site, je ne pouvais pas du tout penser à une solution, alors j'ai décidé d'essayer le rond-point interdit.
Le problème est de trouver m pour lequel f (m) == c pour une fonction f et une constante c données.
Le résultat de l'implémentation sans réfléchir pour le moment est le code suivant.
solution1
import sys
def solve(m):
# f,c est défini
return f(m) == c
def solution1():
limit = int(sys.argv[1])
ans = [m for m in range(limit) if solve(m)]
print ans
Je me suis demandé combien de temps le temps de traitement prendrait, alors j'ai préparé un profileur.
profile
import cProfile
if __name__ == '__main__':
profiler = cProfile.Profile()
profiler.runcall(solution1)
profiler.print_stats()
Et courir.
solution1_profile_result
% python mp.py 100000000
(La solution est omise)
200000003 function calls in 333.009 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
100000000 78.739 0.000 299.934 0.000 mp.py:12(solve)
1 30.856 30.856 333.009 333.009 mp.py:31(solution1)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
100000000 221.195 0.000 221.195 0.000 {pow}
1 2.219 2.219 2.219 2.219 {range}
Quand je me demandais si je connaissais la réponse pour le moment, j'ai entendu une voix venant du côté disant: "Pourquoi ne pas paralléliser www bufefe www?" En pensant "Au fait, je n'ai jamais étudié le traitement parallèle de Python", je vais implémenter une version parallélisée.
solution2
import math
import sys
from multiprocessing import Process, Queue
def task(q, num_range):
#Pour transmettre des données au côté principal via la file d'attente,Il n'y a pas de signification essentielle dans ce programme.
#Mirita Cutter Ducker
q.put([m for m in num_range if solve(m)])
def solution2():
queue = Queue()
limit = int(sys.argv[1])
worker_num = int(sys.argv[2])
task_size = int(math.ceil(float(limit) / float(worker_num)))
#Divisez la liste à traiter,Passer à chaque processus.
# ref. http://iogi.hatenablog.com/entry/split-list-into-sublist
num_ranges = izip_longest(*[iter(range(limit))]*task_size)
processes = [Process(group=None, target=task, args=(queue, num_range))
for num_range in num_ranges]
for process in processes:
process.start()
for process in processes:
print queue.get()
process.join()
Et le temps de traitement est presque de moitié.
solution2_profile_result
% python mp.py 100000000 4
(La solution est omise)
1021 function calls (1018 primitive calls) in 182.498 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 __future__.py:48(<module>)
1 0.000 0.000 0.000 0.000 __future__.py:74(_Feature)
7 0.000 0.000 0.000 0.000 __future__.py:75(__init__)
1 0.005 0.005 0.042 0.042 __init__.py:102(Pipe)
1 0.004 0.004 0.084 0.084 __init__.py:213(Queue)
1 0.000 0.000 0.000 0.000 connection.py:117(Listener)
1 0.000 0.000 0.000 0.000 connection.py:183(Pipe)
1 0.000 0.000 0.000 0.000 connection.py:246(SocketListener)
1 0.013 0.013 0.037 0.037 connection.py:35(<module>)
1 0.000 0.000 0.000 0.000 connection.py:426(ConnectionWrapper)
1 0.000 0.000 0.000 0.000 connection.py:448(XmlListener)
1 0.000 0.000 0.000 0.000 forking.py:113(Popen)
4 0.000 0.000 0.027 0.007 forking.py:115(__init__)
(Abréviation)
L'implémentation précédente utilise la fonction de plage pour générer une liste lors de la division d'une liste. Par conséquent, l'utilisation de la mémoire est excellente.
Ce problème a été résolu en utilisant la fonction xrange au lieu de la fonction range. La fonction xrange renvoie un itérateur au lieu d'une liste, elle ne consomme donc pas de mémoire en même temps.
solution3
import math
import sys
from multiprocessing import Process, Queue
def solution3():
queue = Queue()
limit = int(sys.argv[1])
worker_num = int(sys.argv[2])
task_size = int(math.ceil(float(limit) / float(worker_num)))
gen = xrange(limit)
processes = [Process(
group=None,
target=task,
args=(queue, islice(gen, task_size * i, task_size * (i + 1))))
for i in xrange(worker_num)]
for process in processes:
process.start()
for process in processes:
print queue.get()
process.join()
Donc, exécution + consommation de mémoire à ce moment-là. Le temps d'exécution n'a guère changé, mais la consommation de mémoire a considérablement diminué.
solution3_profile_result
% python mp.py 100000000 4
(La solution est omise)
1019 function calls (1016 primitive calls) in 187.432 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 __future__.py:48(<module>)
1 0.000 0.000 0.000 0.000 __future__.py:74(_Feature)
7 0.000 0.000 0.000 0.000 __future__.py:75(__init__)
1 0.006 0.006 0.047 0.047 __init__.py:102(Pipe)
1 0.005 0.005 0.082 0.082 __init__.py:213(Queue)
1 0.000 0.000 0.000 0.000 connection.py:117(Listener)
1 0.000 0.000 0.000 0.000 connection.py:183(Pipe)
1 0.000 0.000 0.000 0.000 connection.py:246(SocketListener)
1 0.015 0.015 0.041 0.041 connection.py:35(<module>)
1 0.000 0.000 0.000 0.000 connection.py:426(ConnectionWrapper)
1 0.000 0.000 0.000 0.000 connection.py:448(XmlListener)
1 0.000 0.000 0.000 0.000 forking.py:113(Popen)
4 0.000 0.000 0.001 0.000 forking.py:115(__init__)
10 0.000 0.000 0.000 0.000 forking.py:130(poll)
4 0.000 0.000 0.000 0.000 forking.py:146(wait)
1 0.014 0.014 0.019 0.019 forking.py:35(<module>)
(Abréviation)
En Python3, la fonction range renvoie un itérateur appelé classe range, donc la correspondance ci-dessus n'est pas nécessaire. Au contraire, la fonction xrange est obsolète.
// Python3
% python3
Python 3.3.0 (default, Mar 2 2013, 11:44:00)
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.24)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = range(5)
>>> a
range(0, 5)
>>> type(a)
<class 'range'>
>>>
>>> xrange(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
// Python2
% python
Python 2.7.3 (default, May 14 2012, 22:41:33)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
>>> type(a)
<type 'list'>
>>>
Recommended Posts