Остановка многопроцессорной обработки в Python

Я наблюдаю странное поведение многопроцессорного модуля. Кто-нибудь может объяснить, что здесь происходит?

Следующие MWE зависает (работает вечно и без ошибок):

#!/usr/bin/env python3

import multiprocessing

import numpy as np
from skimage import io
from sklearn.cluster import KMeans

def create_model():
    sampled_pixels = np.random.randint(0, 255, (800,3))
    kmeans_model = KMeans(n_clusters=8, random_state=0).fit(sampled_pixels)

def process_image(test, test2):
    image  = np.random.randint(0, 255, (800,3))
    kmeans_model = KMeans(n_clusters=8, random_state=0).fit(image)
    image = kmeans_model.predict(image)

def main():

    create_model()

    with multiprocessing.Pool(1) as pool:

        pool.apply_async(process_image, args=('test', 'test'))

        pool.close()
        pool.join()

if __name__ == "__main__":
    main()

Однако, если я либо удалю строку create_model() ИЛИ изменю

def process_image(test, test2)
# as well as
pool.apply_async(process_image, args=('test', 'test'))

к

def process_image(test)`
# and
pool.apply_async(process_image, args=('test'))

код выполняется успешно, как и должно быть, поскольку аргументы, а также вызов функции create_model() полностью избыточны.


Приложение

> pip list
Package       Version
------------- ---------
imageio       2.34.0
joblib        1.4.0
lazy_loader   0.4
networkx      3.3
numpy         1.26.4
packaging     24.0
pillow        10.3.0
pip           23.2.1
scikit-image  0.23.1
scikit-learn  1.4.2
scipy         1.13.0
threadpoolctl 3.4.0
tifffile      2024.2.12

> python --version
Python 3.12.2
args=('test')) .... это опечатка, в кортежах одного элемента нужна запятая, иначе скобки игнорируются args=('test',)) ... возможно, это не связано
Ahmed AEK 13.04.2024 22:14
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Думаю, я отследил это ошибку/недостаток в GNU OpenMP. Короче говоря, GNU OpenMP, используемый scikit-learn, не является безопасным для форков:

Если ваша программа намерена стать фоновым процессом [...], вы не должны использовать функции OpenMP до ее разветвления. После использования функций OpenMP ветвление разрешено только в том случае, если дочерний процесс не использует функции OpenMP или делает это как совершенно новый процесс (например, после exec()).

Минимальный способ вызвать это:

import multiprocessing
from sklearn.cluster import KMeans

def kmeans():
    KMeans(n_clusters=2, random_state=0).fit([[1, 1], [2, 2]])

kmeans()
with multiprocessing.Pool(1) as pool:
    pool.apply_async(kmeans)
    pool.close()
    pool.join()

О возможных способах смягчения последствий см. по этой ссылке.

Другие вопросы по теме