2015-04-09 2 views
0

У меня есть код, который распараллеляет вызовы функции. Внутри функции я проверяю, существует ли файл, если нет, тогда я его создаю, иначе я ничего не делаю.python multprocessing slow

Я нахожу, что если файлы существуют, то вызов multiprocessing.process имеет довольно большое временное ограничение по сравнению с простым циклом цикла. Ожидается ли это или есть что-то, что я могу сделать, чтобы уменьшить штраф?

def fn(): 
    # Check if file exists, if yes then return else make the file 
    if(not(os.path.isfile(fl))): 
     # processing takes enough time to make the paralleization worth it 
    else: 
     print 'file exists' 


pkg_num = 0 
total_runs = 2500 
threads = [] 

while pkg_num < total_runs or len(threads): 
    if(len(threads) < 3 and pkg_num < total_runs): 
     t = multiprocessing.Process(target=fn,args=[]) 
     pkg_num = pkg_num + 1 
     t.start() 
     threads.append(t) 
    else: 
     for thread in threads: 
      if not thread.is_alive(): 
       threads.remove(thread) 
+3

Не создавайте новый файл для каждого файла, который будет навсегда ... каждый проверяет сотни файлов или что-то в этом роде. –

+1

Вы читаете каждый файл внутри этого оператора if? Дисковый ввод-вывод (например, чтение файлов) не распараллеливается; вы не можете читать из разных частей вашего жесткого диска параллельно, так что вы будете прыгать назад и вперед между каждым файлом, как выполняются ваши рабочие процессы. С вращающимся диском это сильно ухудшит производительность. Если после того, как вы прочтете его, вы столкнетесь с связкой работы с процессором, возможно, это компенсирует это. Конечно, что-то иметь в виду. И, как сказал Йоран, постоянно разворачиваются новые процессы, так как другие выходят накладные расходы. Вместо этого используйте «multiprocessing.Pool». – dano

+1

Еще одна вещь: вы удаляете элементы из 'threads', пока вы перебираете их, что имеет неопределенное поведение в Python и, вероятно, приведет к неправильному поведению. – dano

ответ

1

Там изрядные немного накладные расходы для воспитывающих процессов - вы должны взвесить издержки создания этих процессов против преимущества в производительности, которые вы получите от решений задач одновременно. Я не уверен, что есть достаточно преимуществ для простого вызова ОС, чтобы он был полезен.

Кроме того, для будущих поколений вы должны действительно проверить concurrent.futures.ProcessPoolExecutor; путь, путь чище. Если вы используете 2.7, вы можете вернуть его обратно.

+3

Даже просто использование 'multiprocessing.Pool' будет достаточно чистым. Это не очень ясно из примера, но есть комментарий, в котором говорится, что '# обработка занимает достаточно времени, чтобы сделать ее параллелизуемой стоимостью', я предполагаю, что это означает, что там происходит некоторая обработка за пределами вызова' os.path.isfile' , Трудно сказать, достаточно ли этого, чтобы перевесить процесс нереста накладных расходов. – dano

+1

Да, думаю, он добавил это утверждение после моего ответа. Мне все еще интересно, не связано ли это не с привязкой к IO, а не с процессором, и если он не должен использовать потоки, а не процессы. – jwilner

+0

спасибо @jwilner, я добавил chunkify подпрограмму к коду ... – user308827