Beim Lösen des Code-Puzzles auf einer bestimmten Site fiel mir überhaupt keine Lösung ein, und ich beschloss, den verbotenen Kreisverkehr auszuprobieren.
Das Problem besteht darin, m zu finden, für das f (m) == c für eine gegebene Funktion f und eine Konstante c ist.
Das Ergebnis der Implementierung, ohne vorerst nachzudenken, ist der folgende Code.
solution1
import sys
def solve(m):
# f,c ist definiert
return f(m) == c
def solution1():
limit = int(sys.argv[1])
ans = [m for m in range(limit) if solve(m)]
print ans
Ich fragte mich, wie lange die Verarbeitungszeit dauern würde, und bereitete einen Profiler vor.
profile
import cProfile
if __name__ == '__main__':
profiler = cProfile.Profile()
profiler.runcall(solution1)
profiler.print_stats()
Und Renn.
solution1_profile_result
% python mp.py 100000000
(Die Lösung wird weggelassen)
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}
Als ich mich fragte, ob ich die Antwort vorerst wusste, hörte ich eine Stimme von der Seite, die sagte: "Warum parallelisieren Sie nicht www bufefe www?" Während ich denke "Übrigens, ich habe die Parallelverarbeitung von Python noch nie untersucht", werde ich eine parallelisierte Version implementieren.
solution2
import math
import sys
from multiprocessing import Process, Queue
def task(q, num_range):
#Übergeben von Daten an die Hauptseite über die Warteschlange,Dieses Programm hat keine wesentliche Bedeutung.
#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)))
#Teilen Sie die zu verarbeitende Liste,Übergeben Sie an jeden Prozess.
# 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()
Und die Bearbeitungszeit beträgt fast die Hälfte.
solution2_profile_result
% python mp.py 100000000 4
(Die Lösung wird weggelassen)
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__)
(Abkürzung)
Die vorherige Implementierung verwendet die Bereichsfunktion, um beim Aufteilen einer Liste eine Liste zu generieren. Daher ist die Speichernutzung großartig.
Dieses Problem wurde gelöst, indem anstelle der Bereichsfunktion die Funktion xrange verwendet wurde. Die Funktion xrange gibt den Iterator anstelle einer Liste zurück, sodass nicht alle gleichzeitig Speicher verbraucht werden.
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()
Ausführung + Speicherverbrauch zu diesem Zeitpunkt. Die Ausführungszeit hat sich kaum geändert, aber der Speicherverbrauch hat sich dramatisch verringert.
solution3_profile_result
% python mp.py 100000000 4
(Die Lösung wird weggelassen)
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>)
(Abkürzung)
In Python3 gibt die Bereichsfunktion einen Iterator zurück, der als Bereichsklasse bezeichnet wird, sodass die obige Entsprechung nicht erforderlich ist. Vielmehr ist die xrange-Funktion veraltet.
// 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