Es gab keine output > a given number
Angabe, also habe ich mir nur eine ausgedacht. Nach dem Testen musste ich den Zustand für einen ordnungsgemäßen Betrieb umkehren output < a given number
.
Ich würde einen Pool verwenden, die Prozesse mit einer Rückruffunktion starten, um die Stoppbedingung zu überprüfen, und dann den Pool beenden, wenn er bereit ist. Dies würde jedoch zu einer Racebedingung führen, die es ermöglichen würde, Ergebnisse aus laufenden Prozessen wegzulassen, die nicht beendet werden durften. Ich denke, diese Methode hat nur minimale Änderungen an Ihrem Code und ist sehr einfach zu lesen. Die Reihenfolge der Liste ist NICHT garantiert.
Vorteile: sehr wenig Overhead
Nachteile: könnten fehlende Ergebnisse haben.
Methode 1)
from scipy import *
import multiprocessing
import matplotlib.pyplot as plt
def stop_condition_callback(ret):
output.append(ret)
if ret < stop_condition:
worker_pool.terminate()
def func(x, y, ):
return y / x
def main(y, xmin, xmax, dx):
x = arange(xmin, xmax, dx)
print("Number of calculations: %d" % (len(x)))
# add calculations to the pool
for i in x:
worker_pool.apply_async(func, (i, y,), callback=stop_condition_callback)
# wait for the pool to finish/terminate
worker_pool.close()
worker_pool.join()
print("Number of results: %d" % (len(output)))
return x, asarray(output)
def demo():
x, z_list = main(2., 1., 30., .1)
plt.plot(z_list, label='desired range')
plt.show()
output = []
stop_condition = 0.1
worker_pool = multiprocessing.Pool()
demo()
Diese Methode hat mehr Overhead, ermöglicht jedoch Prozesse, deren Abschluss begonnen hat. Methode 2)
from scipy import *
import multiprocessing
import matplotlib.pyplot as plt
def stop_condition_callback(ret):
if ret is not None:
if ret < stop_condition:
worker_stop.value = 1
else:
output.append(ret)
def func(x, y, ):
if worker_stop.value != 0:
return None
return y / x
def main(y, xmin, xmax, dx):
x = arange(xmin, xmax, dx)
print("Number of calculations: %d" % (len(x)))
# add calculations to the pool
for i in x:
worker_pool.apply_async(func, (i, y,), callback=stop_condition_callback)
# wait for the pool to finish/terminate
worker_pool.close()
worker_pool.join()
print("Number of results: %d" % (len(output)))
return x, asarray(output)
def demo():
x, z_list = main(2., 1., 30., .1)
plt.plot(z_list, label='desired range')
plt.show()
output = []
worker_stop = multiprocessing.Value('i', 0)
stop_condition = 0.1
worker_pool = multiprocessing.Pool()
demo()
Methode 3) Vorteile: Es werden keine Ergebnisse ausgelassen.
Nachteile: Dieser Schritt geht weit über das hinaus, was Sie normalerweise tun würden.
nimm Methode 1 und füge hinzu
def stopPoolButLetRunningTaskFinish(pool):
# Pool() shutdown new task from being started, by emptying the query all worker processes draw from
while pool._task_handler.is_alive() and pool._inqueue._reader.poll():
pool._inqueue._reader.recv()
# Send sentinels to all worker processes
for a in range(len(pool._pool)):
pool._inqueue.put(None)
Dann ändern stop_condition_callback
def stop_condition_callback(ret):
if ret[1] < stop_condition:
#worker_pool.terminate()
stopPoolButLetRunningTaskFinish(worker_pool)
else:
output.append(ret)