Nano Hash - криптовалюты, майнинг, программирование

Многопроцессорный пул Python возвращает тот же результат в цикле for

Я использую multiprocessing.Pool в Python 3.6 через Spyder 3.6.5 на компьютере с Windows 10. Цель состоит в том, чтобы получить выходные данные простой квадратичной функции путем импорта нескольких входных данных (в этом примере для практических целей включены только 4 значения). Код ниже работает нормально:

import numpy as np
import multiprocessing

from multiprocessing import Pool

data=[]
data.append(np.array([1,2]))
data.append(np.array([4,5]))

Output=np.zeros((2,2))


for i in range (0,2):

    data1=data[i]

    def square(x):
        return x*x

    if __name__ == '__main__':
        __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"
        with Pool(multiprocessing.cpu_count()) as p:
            output = p.map(square, data1, chunksize=10)
            p.close()
            output=np.asarray(output)
            Output[i]=output

в то время как в случае, когда я хочу указать значения входной квадратной функции (x) как:

def square(ii):
    x=data1[ii]
    return x*x

цикл for выполняется два раза (из-за «для i в диапазоне (0,2)»), но результаты p.map одинаковы при каждом запуске и равны второму запуску, т.е. вместо того, чтобы быть Output=np.array ([[1,4],[16,25]]) Я получаю Output=np.array([[16,25],[16,25]]). Кажется, что цикл for выполняется два раза с i=1, а не как в первом цикле i=0 и во втором i=1.

Любые идеи о том, что я делаю неправильно?


  • Нет времени разбираться в деталях, но 2 комментария: 1. Странно размещать if __name__ == '__main__': внутри цикла for. То же самое для with Pool(). Первый проверяет, не импортирована ли программа, поэтому она должна быть с отступом 0. Второй - если порождает пул рабочих. Это долгая операция, поэтому более эффективно размещать циклы for внутри оператора with. 02.07.2018

Ответы:


1

Замыкания в python не копируют значения переменных, которые они закрывают. Они просто сохраняют ссылку на эту область. Во второй попытке функция square обращается к data1 так, как если бы это было разное значение в обеих итерациях, но на самом деле это ссылка на одну и ту же базовую переменную. К тому времени, когда многопроцессорный модуль запускает новый процесс и вызывает square, переменная уже изменилась.

Попробуйте это, например:

res = []
for i in range(5):
    def square():
        return i * i
    res.append(square)


print([f() for f in res])

Что касается решения, вы можете вручную создать новую область с соответствующим значением на каждой итерации.

Вызов функции создает новую область, поэтому вы можете определить вспомогательную функцию, подобную этой, вне цикла.

def square_creater(data1):
    def square(ii):
        x = data1[ii]
        return x * x
    return square

а затем на каждой итерации используйте

square = square_creater(data1)

Это должно работать.

02.07.2018
  • Дорогой Мерлин, спасибо за мгновенный ответ. Я вижу на вашем примере проблему закрытия в python. Пытаясь изменить код, следуя вашим указаниям, я получаю сообщение об ошибке «Не удается собрать локальный объект 'square_creator.‹locals›.square» в строке output = p.map(square, range(2), chunksize=10). Вы можете увидеть новую версию кода 02.07.2018
  • def квадрат_создатель(данные1): def квадрат(ii): x = данные1[ii] вернуть x * x вернуть квадрат для я в диапазоне (0,2): данные1=данные[i] квадрат = квадрат_создатель(данные1) если name == 'main': spec = ModuleSpec(name='builtins', loader=‹class '_frozen_importlib.BuiltinImporter'›) с пулом (многопроцессорный .cpu_count()) как p: вывод = p.map (квадрат, диапазон (2), размер фрагмента = 10) p.close() вывод = np.asarray (вывод) Вывод [i] = вывод 02.07.2018
  • @GeorgeKouskoulis Я только что попробовал ваш новый код с исходным квадратным определением и получил ожидаемое [[1., 4.], [16., 25.]]. У вас есть полный исходный код файла, который возвращает [[16, 25], [16, 25]]? 02.07.2018
  • Код, который возвращает [[16,25],[16,25]]: data=[] data.append(np.array([1,2])) data.append(np.array([4,5])) Output=np.zeros((2,2)) for i in range (0,2): data1=data[i] def square(ii): x=data1[ii] return x*x if __name__ == '__main__': __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)" with Pool(multiprocessing.cpu_count()) as p: output = p.map(square, range(2), chunksize=10) p.close() p.join() output=np.asarray(output) Output[i]=output 02.07.2018
  • @GeorgeKouskoulis Опять же, я получаю [[1, 4], [16, 25]], как на своей машине, так и на онлайн 02.07.2018
  • Ты прав! На Python онлайн-результаты [[1, 4], [16, 25]]! Хотя на Spyder и Python IDLE есть [[16, 25], [16, 25]]. 02.07.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..