Почему добавление многопроцессорности не позволяет python найти мою скомпилированную программу c?

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

Например, со следующим тестовым кодом:

#include <omp.h>

int main() {
    int thread_id;
#pragma omp parallel
    {
        thread_id = omp_get_thread_num();
    }
    return 0;
}

Здесь я компилирую программу, затем превращаю ее в файл .so с помощью команды

gcc -fopenmp -o theories/test.so -shared -fPIC -O2 test.c

Затем я пытаюсь запустить указанный код из test.py:

from ctypes import CDLL
import os

absolute_path = os.path.dirname(os.path.abspath(__file__))
# imports the c libraries
test_lib_path = absolute_path + '/theories/test.so'
test = CDLL(test_lib_path)
test.main()
print('complete')

Я получаю следующую ошибку:

FileNotFoundError: Could not find module 'C:\[my path]\theories\test.so' (or one of its dependencies). Try using the full path with constructor syntax.

Однако, когда я комментирую элемент многопроцессорности, чтобы получить следующий код:

#include <omp.h>

int main() {
    int thread_id;
    /*
#pragma omp parallel
    {
        thread_id = omp_get_thread_num();
    }
    */
    return 0;
}

Затем у меня есть идеальное выполнение с программой python, распечатывающей «завершено» в конце.

Мне интересно, как это произошло, и как код, казалось бы, может быть скомпилирован нормально, но затем создавать проблемы только после того, как он вызывается из python (также я проверил, и файл фактически создан).

ОБНОВЛЕНИЯ:

  1. Теперь я проверил, что у меня установлена ​​libgomp-1.dll.
  2. Я удалил и переустановил MinGW, без каких-либо изменений.
  3. Я установил другую 64-битную версию gcc и, используя другую (64-битную версию python 3.10) версию python, воспроизвел ту же ошибку. Это также имеет libgomp-1.dll.

Я не могу воспроизвести проблему при повторе с этим bash-кодом. То же самое на другой машине. Вы уверены, что каталог существует? Правильно ли настроена среда и правильно ли установлены GCC/GOMP? Является ли библиотека so правильной? Кроме того, судя по пути к файлу, похоже, что ваша ОС — это Windows, но файлы SO являются общей библиотекой в ​​основном для Linux, а не для Windows. Вы используете WSL? Можете ли вы указать свою целевую ОС?

Jérôme Richard 02.01.2023 01:41

@ JérômeRichard Я думал, что мой gcc был установлен правильно, но, учитывая эту ошибку, я начинаю думать, что это может быть не так. Кроме того, моя система действительно Windows, у меня просто появилась дурная привычка использовать файлы .so, потому что я видел это в случайном учебнике в Интернете, и, похоже, в целом он работает нормально. Не уверены, что это может быть еще одним источником проблем?

Arkleseisure 02.01.2023 01:47

В Windows должна быть найдена DLL GOMP, иначе загрузка не будет выполнена. Вам нужно настроить переменную среды PATH, чтобы DLL GOMP можно было найти и загрузить при загрузке вашей динамической библиотеки. Кроме того, я посоветовал вам использовать стандартное расширение (файлы .dll в Windows), чтобы избежать странных проблем, хотя здесь это может не иметь значения.

Jérôme Richard 02.01.2023 01:57

@ JérômeRichard нужно ли устанавливать GOMP независимо от GCC?

Arkleseisure 02.01.2023 02:24

AFAIK, как правило, нет, но это зависит от того, как был установлен GCC (он может быть скомпилирован без поддержки GOMP, хотя это необычно). GOMP — это отдельная библиотека, обычно расположенная с другими DLL. В моей Windows GCC был установлен с MSys, он добавлен в переменную среды PATH и находится в C:\msys64\mingw64\bin (libgomp-1.dll). У вас есть такой файл DLL?

Jérôme Richard 02.01.2023 02:47

@ JérômeRichard Я только что посмотрел, и у меня действительно есть такой файл.

Arkleseisure 02.01.2023 16:14

Обратите внимание, что PATH не обновляется для всех приложений динамически. Вы должны проверить, что он был изменен. Самое простое решение для обеспечения изменения PATH в Windows — перезагрузить машину.

Jérôme Richard 03.01.2023 21:46

@JérômeRichard Я изменил путь вручную и перезагрузил визуальную студию ... Я уже проверил, что это обновило используемый путь, изменив путь на несуществующий. Поскольку это дало ожидаемую ошибку, а скомпилированные версии моего кода работают на 40% быстрее с 64-битной версией, я предполагаю, что новый gcc используется правильно.

Arkleseisure 04.01.2023 17:17
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
8
120
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обратите внимание, где в сообщении об ошибке говорится «или одна из его зависимостей».

Попробуйте запустить ldd в файле test.so, чтобы убедиться, что он полностью связан.

РЕДАКТИРОВАТЬ1:

Как правило, gcc требует binutils. (Думаю, в ms-windows их можно комбинировать.) Это означает, что у вас должен быть objdump.

Если вы запустите objdump -x test.so|more, вы должны увидеть несколько строк, начинающихся с «НУЖНО» в «Динамическом разделе». Это общие библиотеки, необходимые для этого.

насколько я понимаю, ldd - это команда только для Linux. Я знаю, что использую файлы .so, но в настоящее время я работаю на компьютере с Windows, поэтому у меня возникают проблемы с этим.

Arkleseisure 02.01.2023 01:52

objdump работал нормально, но не распечатывал динамический раздел, и я не видел "НЕОБХОДИМО", о котором вы говорили. Однако был раздел под названием «Импорт таблиц», в котором говорилось, что он импортировал файлы «KERNEL32.dll», «msvcrt.dll» и «libgomp-1.dll». Заглянув в свой диспетчер установки MINGW, я увидел, что у меня установлен пакет mingw32-libgomp-dll, который, как мне сказали, должен дать мне файл libgomp-1.dll. Пакет имеет версию 9.2.0-2, и в версиях он имеет флаг «FIXME: таблица данных недоступна; компилятор для этой категории данных еще не реализован».

Arkleseisure 02.01.2023 16:11

Я думаю, что это единственное, что казалось неправильным.

Arkleseisure 02.01.2023 16:12
Ответ принят как подходящий

Я думаю, что это имеет ту же основную причину, что и [SO]: не удается импортировать модуль dll в Python (@ответ CristiFati) (также проверьте [SO]: PyWin32 и Python 3.8.0 (@ответ CristiFati) ).

.dll (.so) загружается только тогда, когда его зависимости успешно загружены (рекурсивно).
[SO]: Python Ctypes - загрузка dll выдает OSError: [WinError 193] %1 не является допустимым приложением Win32 (@ответ CristiFati) фокусируется на другой ошибке, но охватывает эту тему.

При комментировании вызова omp_get_thread_num компоновщик больше не связывает test.so с libgomp*.dll (поскольку от него ничего не нужно), и код работает нормально (находятся все необходимые .dll).

Чтобы решить эту проблему, вы должны добавить в os.add_dll_directory (перед попыткой загрузить .so):

  1. Каталог libgomp*.dll

  2. Каталог bin MinGW

  3. Любой другой каталог, который может содержать необходимые библиотеки .dll (зависимые)

Чтобы увидеть зависимости .dll, проверьте [SO]: Обнаружение отсутствующего модуля с помощью командной строки («ошибка загрузки DLL») (@ответ CristiFati).

Примечания:

Спасибо, хотя я, вероятно, должен добавить, что наиболее удобным ответом на самом деле является ответ Mad Physicist в вашей первой ссылке, где упоминается, что на самом деле вам просто нужно установить winmode = 0 в вызове CDLL.

Arkleseisure 07.01.2023 00:07

Так вы говорите, что только изменение test = CDLL(test_lib_path, winmode=0) решает проблему?

CristiFati 07.01.2023 08:55

Да, насколько я понимаю, по умолчанию используется winmode = None, что, согласно этому ответу, «похоже, не реагирует на изменения в os.environ ['PATH'], sys.path или os.add_dll_directory».

Arkleseisure 07.01.2023 09:57

Эта часть (ответа) не совсем верна (также проверьте комментарии). Я предполагаю, что у вас есть каталог libgomp*.dll в вашем PATH. Я отредактирую свой (другой) ответ, чтобы добавить дополнительную информацию (и, возможно, тестовый код).

CristiFati 07.01.2023 10:12

Ага, да, я вижу, я думаю, что у меня действительно есть каталог для gomp dll на моем пути, поэтому я предполагаю, что это исправило это.

Arkleseisure 07.01.2023 10:22

Я добавил дополнительную информацию, которая, я надеюсь, прольет свет на тему.

CristiFati 07.01.2023 13:31

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