Превратите код цикла for в многопоточный код с максимальным количеством потоков - PullRequest
0 голосов
/ 10 октября 2019

Справочная информация: Я пытаюсь сделать сотни симуляций димолы с помощью интерфейса python-dymola. Мне удалось запустить их в цикле. Теперь я хочу, чтобы они работали в режиме многопоточности, чтобы я мог запускать несколько моделей параллельно (что будет намного быстрее). Поскольку, вероятно, никто не использует интерфейс, я написал некоторый простой код, который также показывает мою проблему:

1: Превратить цикл for в определение, которое выполняется в другой цикл for НО и def, ицикл for совместно использует одну и ту же переменную 'i'.

2: превратить цикл for в определение и использовать многопоточность для его выполнения. Цикл for запускает команду одну за другой. Я хочу запускать их параллельно с максимумом x потоков одновременно. Результат должен быть таким же, как при выполнении цикла for

Пример кода:

import os

nSim = 100
ndig='{:01d}'

for i in range(nSim):
    os.makedirs(str(ndig.format(i)))

Обратите внимание, что имена созданных каталогов - это просто числа изпетля (это важно). Теперь вместо использования цикла for я хотел бы создать каталоги с многопоточностью ( примечание: вероятно, это неинтересно для этого короткого кода, но при вызове и выполнении сотен имитационных моделей определенно интересно использовать несколькоthreading ).

Итак, я начал с чего-то простого, подумал я, превратив цикл for в функцию, которая затем запускается внутри другого цикла for и надеясь получить тот же результат, что и в случае цикла for. код цикла выше, но получил эту ошибку: AttributeError: у объекта 'NoneType' нет атрибута 'start' (примечание: я только начал с этого, потому что раньше я не использовал оператор def, а пакет потокатакже новый. После этого я буду развиваться в сторону многопоточности.)

1:

import os

nSim = 100
ndig='{:01d}'

def simulation(i):
    os.makedirs(str(ndig.format(i)))

for i in range(nSim):
    simulation(i=i).start

После того, как это не удалось, я попытался эволюционировать в многопоточность(преобразование цикла for во что-то, что делает то же самое, но с многопоточностью и тем, что код выполняется параллельно вместо одного за другим и с максимальным(число потоков):

2:

import os
import threading


nSim = 100
ndig='{:01d}'

def simulation(i):
    os.makedirs(str(ndig.format(i)))

if __name__ == '__main__':
    i in range(nSim)
    simulation_thread[i] = threading.Thread(target=simulation(i=i))
    simulation_thread[i].daemon = True
    simulation_thread[i].start()

К сожалению, эта попытка также не удалась, и теперь я получил ошибку: NameError: name 'i'не определено

У кого-нибудь есть предложения по вопросам 1 или 2?

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Оба примера являются неполными. Вот полный пример. Обратите внимание, что target получает имя функции target=simulation и кортеж ее аргументов args=(i,). Не вызывайте функцию target=simulation(i=i), потому что она просто передает результат функции, который в данном случае эквивалентен target=None.

import threading

nSim = 100

def simulation(i):
    print(f'{threading.current_thread().name}: {i}')

if __name__ == '__main__':
    threads = [threading.Thread(target=simulation,args=(i,)) for i in range(nSim)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()

Выход:

Thread-1: 0
Thread-2: 1
Thread-3: 2
 .
 .
Thread-98: 97
Thread-99: 98
Thread-100: 99

Обратите внимание, что вы обычно не хотите больше потоков, чем процессоры, которые вы можете получить из multiprocessing.cpu_count(). Вы можете использовать создание пула потоков и использовать queue.Queue для публикации работы, выполняемой потоками. Пример приведен в документации Python Queue .

0 голосов
/ 10 октября 2019
  1. Невозможно вызвать .start, как это

    simulation(i=i).start
    

    для объекта без потоков. Кроме того, вам также необходимо импортировать модуль

  2. Кажется, вы забыли добавить 'for' и сделать отступ для кода в вашем цикле

    i in range(nSim)
    simulation_thread[i] = threading.Thread(target=simulation(i=i))
    simulation_thread[i].daemon = True
    simulation_thread[i].start()
    

    в

    for i in range(nSim):
        simulation_thread[i] = threading.Thread(target=simulation(i=i))
        simulation_thread[i].daemon = True
        simulation_thread[i].start()
    
...