Реальный код, который я хочу оптимизировать, слишком сложен, чтобы включать его здесь, поэтому вот упрощенный пример:
def enumerate_paths(n, k):
"""
John want to go up a flight of stairs that has N steps. He can take
up to K steps each time. This function enumerate all different ways
he can go up this flight of stairs.
"""
paths = []
to_analyze = [(0,)]
while to_analyze:
path = to_analyze.pop()
last_step = path[-1]
if last_step >= n:
# John has reach the top
paths.append(path)
continue
for i in range(1, k + 1):
# possible paths from this point
extended_path = path + (last_step + i,)
to_analyze.append(extended_path)
return paths
и вывод выглядит так
>>> enumerate_paths(3, 2)
[(0, 2, 4), (0, 2, 3), (0, 1, 3), (0, 1, 2, 4), (0, 1, 2, 3)]
Результат может показаться запутанным, поэтому здесь есть объяснение. Например, (0, 1, 2, 4)
означает, что Джон может посетить и поставить ногу на первый, второй и четвертый этап хронологии, и, наконец, он останавливается на шаге 4, потому что ему нужно только подняться на 3 шага.
Я пытался включить multiprocessing
в этот фрагмент, но не наблюдал никакого увеличения производительности, даже немного!
import multiprocessing
def enumerate_paths_worker(n, k, queue):
paths = []
while not queue.empty():
path = queue.get()
last_step = path[-1]
if last_step >= n:
# John has reach the top
paths.append(path)
continue
for i in range(1, k + 1):
# possible paths from this point
extended_path = path + (last_step + i,)
queue.put(extended_path)
return paths
def enumerate_paths(n, k):
pool = multiprocessing.Pool()
manager = multiprocessing.Manager()
queue = manager.Queue()
path_init = (0,)
queue.put(path_init)
apply_result = pool.apply_async(enumerate_paths_worker, (n, k, queue))
return apply_result.get()
Список Python to_analysis
действует так же, как очередь задач, и каждый элемент в этой очереди может обрабатываться отдельно, поэтому я думаю, что эта функция потенциально может быть оптимизирована за счет использования многопоточности / обработки. Также обратите внимание, что порядок пунктов не имеет значения. Фактически, при его оптимизации вы можете вернуть набор Python, массив Numpy или фрейм данных Pandas, если они представляют один и тот же набор путей.
Бонусный вопрос : Какую производительность я могу получить, используя такие научные пакеты, как Numpy, Pandas или Scipy, для таких задач?