Как применить карту уменьшить подход в python - PullRequest
1 голос
/ 03 марта 2020

Я пытаюсь выполнить вычисления Монте-Карло параллельно, используя python. Проблема чрезвычайно параллельна: мне нужно вычислить функцию N раз и сложить результат вместе, каждое вычисление является независимым, и сложение является простым сложением между таблицами.

До сих пор я пробовал два подхода:

  1. Использование multiprocessing.map() и затем python reduce. Проблема в том, что мне не хватает памяти, потому что карта хранит все данные, даже если мне это не нужно. Код выглядит следующим образом:

    from multiprocessing import Pool
    import tqdm
    import numpy as np
    
    n_cpu = 8
    pool = Pool(n_cpu)
    out1 = list(tqdm.tqdm(pool.imap_unordered(f, args, chunksize = 1000)))
    out = reduce(np.add, out1)
    

    Таким образом, я получаю плохое масштабирование с помощью n_cpu, и код вылетает из-за ошибки памяти, если размер ввода len(args) слишком велик.

  2. Я попытался решить, используя pyspark и следующий код:

    import pyspark, findspark
    import numpy as np
    
    findspark.init()
    number_cores = 8
    memory_gb = 8
    conf = (
        pyspark.SparkConf()
            .setMaster('local[{}]'.format(number_cores))
            .set('spark.driver.memory', '{}g'.format(memory_gb))
    )
    sc = pyspark.SparkContext(conf=conf)
    out = sc.parallelize(range(N_samples)).repartition(number_cores).map(function).reduce(lambda a, b: np.add(a, b))
    

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

Мой вопрос:
Есть ли способ улучшить масштабирование кода с количеством ядер? Есть ли способ использовать многопроцессорность imap_unordered() и уменьшить его до завершения вычислений?

1 Ответ

0 голосов
/ 03 марта 2020

Поправьте меня, если я ошибаюсь, но обобщу вашу проблему:

У вас есть 1 машина с несколькими ядрами, и вы пытаетесь запустить какой-то алгоритм и хотите добиться максимальной производительности.

Если приведенное выше утверждение верно, то Spark, скорее всего, не то, что вам нужно. Spark в первую очередь предназначен для распределенных вычислений, т. Е. Если у вас несколько машин, то вы можете распределять свою работу и выполнять вычисления быстрее.

Если у вас только одна машина - вы вряд ли сможете добиться более высокой производительности, чем любой многопоточный подход, поскольку Spark делает много вещей, которые не требуются для вычислений на одной машине.

...