Как я могу обеспечить повторяемость при распараллеливании эксперимента со случайным сеянием? - PullRequest
0 голосов
/ 08 октября 2018

Я использую Mydia для извлечения случайных кадров из видео.Поскольку у меня много видео, я хочу распараллелить этот рабочий процесс, сохраняя повторяемость.mydia.Videos принимает случайное начальное число, что важно для обеспечения повторяемости.Теперь мне нужно поработать над фрагментом распараллеливания.

Учитывая n видео и случайное начальное число r, как я могу убедиться, что извлеченные кадры для каждого видео одинаковы, независимо от количества рабочих?Я особенно заинтересован в алгоритмическом компоненте, а не в коде.

Моя первоначальная мысль заключалась в использовании multiprocessing.Pool.Однако при выборке кадров будет условие гонки, если время завершения процессов не определено;то есть, если proc 1 занимает больше времени, чем proc 0, отснятые кадры из класса Videos будут отличаться от того, если proc 0 занимает больше времени, чем proc 1.

1 Ответ

0 голосов
/ 09 октября 2018

Мое решение немного неортодоксально, потому что оно зависит от библиотеки.Mydia позволяет передавать кадры для извлечения вместо того, чтобы заставить Videos клиента производить сэмплирование напрямую.Это дает мне возможность предварительно рассчитать кадры для выборки в родительском процессе.Делая это, я могу «высмеивать» случайность в подпроцессах, создавая новый Videos с этими кадрами.Например:

class MySampler:
   def __init__(self, input_directory: Path, total_frames: int, num_frames: int, fps: int):
       self.input_directory = Path(input_directory)

       self.frames_per_video = [
            self.__get_frame_numbers_for_each_video(total_frames, num_frames, fps)
            for _ in self.input_directory.glob("*.mp4")
        ]

    @staticmethod
    def get_reader(num_frames: int, frames: List[int]):
        # ignores the inputs and returns samples the frames that its constructed with
        return Videos(target_size=(512, 512), num_frames=num_frames, mode=lambda *_: frames)

, и тогда я могу просто распараллелить это:

   def sample_frames(self, number_of_workers: int):
        pool = Pool(processes=number_of_workers)    
        videos = list(self.input_directory.glob("*.mp4"))

        pool.starmap_async(self.read_video, zip(self.frames_per_video, videos))    

        pool.close()
        pool.join()

, где read_video - это метод, который вызывает get_reader и выполняет чтение.

...