Как выполнять многопроцессорную обработку с использованием Python для .NET в Windows?

Теперь я разрабатываю приложение С#, работающее в Windows. Некоторые из процессов написаны на Python, который вызывается через pythonnet (Python для .NET). Процессы очень тяжелые вычисления, поэтому я хочу сделать их параллельно.

Они ограничены ЦП и могут обрабатываться независимо.

Насколько я знаю, есть два возможных способа реализовать это:

  • Запуск нескольких исполняемых файлов Python
    Первый способ - запуск нескольких интерпретаторов Python, но это кажется неосуществимым. Поскольку pythonnet может управлять только одним интерпретатором, инициализированным статическим методом, PythonEngine.Initialize().
    Из документации Python.NET:

    Важное примечание для встроенных приложений:. Python не является файловым потоком и использует глобальную блокировку интерпретатора, чтобы позволить многопоточным приложениям безопасно взаимодействовать с интерпретатором Python. Гораздо больше информации об этом можно найти в документации на Python C-API на веб-сайте www.python.org.
    При встраивании Python в управляемое приложение вы должны управлять GIL так же, как и при встраивании Python в приложение C или С++.
    Прежде чем взаимодействовать с любым из объектов или API, предоставляемых пространством имен Python.Runtime, вызывающий код должен получить блокировку глобального интерпретатора Python, вызвав метод PythonEngine.AcquireLock. Единственным исключением из этого правила является метод PythonEngine.Initialize, который можно вызвать при запуске без получения GIL.

  • Использовать пакет многопроцессорности в Python
    Другой способ - использовать пакет многопроцессорности. Согласно документации Python, следующий оператор необходим, если код работает в Windows для обеспечения конечного процесса обновления:
    if __name__ == "__main__":
    Однако функция, написанная на Python, берется как часть модуля, так как она встроена в .NET.
    Например, следующий код является исполняемым, но порождает процессы бесконечно.

//C#
static void Main(string[] args)
    {
        using (Py.GIL())
        {
            PythonEngine.Exec(
                "print(__name__)\n" + //output is "buitlins"
                "if __name__ == 'builtins':\n" +
                "   import test_package\n" +  //import Python code below
                "   test_package.async_test()\n"
                );
        }
    }
# Python
import concurrent.futures

def heavy_calc(x):
    for i in range(int(1e7) * x):
        i*2

def async_test():
    # multiprocessing
    with concurrent.futures.ProcessPoolExecutor(max_workers=8) as executor:
        futures = [executor.submit(heavy_calc,x) for x in range(10)]
        (done, notdone) = concurrent.futures.wait(futures)
        for future in futures:
            print(future.result())

Есть ли хорошая идея решить вышеупомянутую проблему? Приветствуются любые комментарии. Спасибо заранее.

Ответ 1

Для каждого вызова python, 1. Создайте appDomain 2. Создайте задачу в appdomain, которая будет запускать python асинхронно.

Поскольку это отдельный AppDomains, статические методы будут независимыми.

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