ImportError: File.so неопределенный символ: PyInterpreterState_GetID - PullRequest
0 голосов
/ 07 апреля 2019

При Cythonizing файла и запуске его через импорт, появляется ошибка, которая утверждает, что есть проблема с получением состояния интерпретатора Python.

Удаление многопроцессорного кода, например multiprocessing.start (); переключение на собственный prange Cython ().

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

Cython 0.29.6 Python 3.7

сборка с использованием

pyhton3 setup.py build_ext --inplace

Где файл setup.py содержит

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

ext_modules = [Extension("Logic", ["Logic.pyx"], extra_compile_args=['-Ofast'],)]
setup(name="Logic", ext_modules=cythonize("Logic.pyx"))

И код проблемы ... Ожидается небольшой список ошибок, но состояние интерпретатора не было одним из них.

import secrets
import os
import time
import Cython

cdef list race = ["Asian", "Black", "White"]
cdef list hair = ["Brown", "Brown", "Brown", "Brown", "Black", "Black", "Black", "Blond", "Blond", "Red"]
cdef list eyes = ["Brown", "Brown", "Brown", "Blue", "Blue", "Blue", "Green", "Green", "Grey", "Hazel"]
cdef list gender = ["Female", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "X", "XXY"]
cdef long age_limit_elder = 115
cdef long weight_limit = 400
cdef long age_limit_adult = 60
cdef long age_limit_child = 18
cdef long weight_limit_infant = 15
cdef long age_limit_infant = 4
cdef long population = 4873057333
cdef long infant = 633497453  # 13%
cdef long child = 1461917200  # 30%
cdef long adult = 2095414652  # 43%
cdef long elder = 682228028  # 14%
cdef list infant_population = []
cdef list child_population = []
cdef list adult_population = []
cdef list elder_population = []

cdef list adult_race_pool = []

cpdef dict adult_generation(long adult=adult, long age_limit_adult=age_limit_adult, long weight_limit=weight_limit, list race=race, list hair=hair, list eyes=eyes, list gender=gender, long age_limit_child=age_limit_child):
    cdef long age_ = secrets.choice(range(age_limit_child, age_limit_adult))
    cdef long weight_ = secrets.choice(range(90, weight_limit))
    cdef str race_ = secrets.choice(race)
    cdef str hair_ = secrets.choice(hair)
    cdef str eyes_ = secrets.choice(eyes)
    cdef str gender_ = secrets.choice(gender)
    # adult_population.append({"AGE": age_, "WEIGHT": weight_, "RACE": race_, "HAIR": hair_, "EYES": eyes_, "GENDER": gender_})
    return {"AGE": age_, "WEIGHT": weight_, "RACE": race_, "HAIR": hair_, "EYES": eyes_, "GENDER": gender_}

# adult_generation()
# cdef long adult_processes = adult // 4
# adult_processes = 10000
# cdef long adult_processes = 100000
cdef long adult_processes = adult  # Fallback
cdef long adult_percent = adult_processes // 10000
cdef double percent = 0
cdef long current = 0
cdef double t1 = time.time()
cdef double master = t1
cdef long i

for i in Cython.parallel.prange(adult_processes, nogil=True):
    if current == adult_percent:
        percent += 0.01
        t2 = time.time()
        t3 = t2 - t1
        os.system("tput reset")
        print(f"{percent}% Complete | {current} Profiles in {t3} Seconds")
        current = 0
        t1 = time.time()
    adult_population.append(adult_generation())
    current += 1

cdef long F = 0
cdef long M = 0
cdef long X = 0
cdef long XXY = 0

cdef dict item

for item in adult_population:
    if item["GENDER"] == "Female":
        F += 1
    elif item["GENDER"] == "Male":
        M += 1
    elif item["GENDER"] == "X":
        X += 1
    elif item["GENDER"] == "XXY":
        XXY += 1
    else:
        pass


print(f"FEMALE: {F}")
print(f"MALE: {M}")
print(f"X: {X}")
print(f"XXY: {XXY}")
print(f"Total Time: {time.time() - master} Seconds")

Результатом должен быть просто гигантский список псевдослучайных людей, как в версии Python, но без нечетного ограничения ЦП в 70% для всех потоков / ядер.

Однако в Cython при параллельной или многообработанной обработке он возвращает «неопределенный символ: PyInterpreterState_GetID» при импорте и просто завершает работу.

Тестирование проводилось с меньшими числами, так как текущие числа занимают 146 дней обработки ... Изменение количества результатов по-прежнему приводит к ошибке.

Ожидалось, что он зацикливается на «предмете cdef dict», но опять же, он даже не доходит до этого.

1 Ответ

0 голосов
/ 07 апреля 2019

Я не могу сказать, что это определенный ответ, но я заметил, что вывод ошибок Python был существенно коротким. Я потратил немного времени, и игра и прямая компиляция кода Cython во встроенный пакет. Этот пакет предоставил полные сообщения об ошибках, хотя он был в беспорядке, он все еще вел куда-то.

Состояние интерпретатора, похоже, как-то связано с многопоточностью / многопоточностью, поэтому я настроил эту часть и обнаружил, что вывод ошибок выдает жалобу на GIL. По-видимому, ошибка, переданная Python, была получена от Cython, но не отображалась пользователю до тех пор, пока она не была скомпилирована как отдельное приложение «C».

Эта ошибка, по-видимому, сосредоточена вокруг GIL, а вывод жалуется на то, что он не может удалить GIL из функций, которые нуждаются в GIL, а именно, из каждого фрагмента кода Python, кроме return, yield, print, simple math и т. Д. ..

Итак, prange и его параллельная способность очень близки к бесполезным для тех, кто хочет улучшить чистый Python-скрипт. Так как все, что зависит от def, open, модуля многопроцессорной обработки или чего-то еще Pythonic, выдаст эту ошибку, и если тот, кто его использует, будет тестировать свой код Cython через импорт Python, они просто окажутся в тупике, с одним ошибка строки, которая не появляется в результатах поиска Google.

Исправление ошибки prange требует переписывания всего того, с чем взаимодействует в C, или импорта чего-то, что использует C вместо Python. Это снова делает его менее полезным для чистого разработчика Python.

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

...