Как выделить больше памяти для моего docker контейнера, выполняющего команду g cc? - PullRequest
1 голос
/ 16 апреля 2020

Я должен скомпилировать C код, который содержит python функцию. У меня есть 64-битная машина Ubuntu 19, и мне нужно скомпилировать код C для моей raspberry pi 3model b +, в которой работает raspbian stretch. Для этого я следовал https://raspberrypi.stackexchange.com/a/109524/116139, чтобы создать контейнер docker с нужной мне стретч-версией. Мой docker stats:


CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %                 NET I/O             BLOCK I/O           PIDS
14b303f257da        DOCKER_CONTAINER   0.00%               13.68MiB / 7.776GiB   0.17%               6.51MB / 26.6kB     19.4MB / 41kB       2

Внутри контейнера, работает top:

    1 root      20   0 4241352  12308   4892 S  0.0  0.2   0:00.50 bash         
  133 root       0   0 4241096  12048   4972 R  0.0  0.1   0:00.00 top 

Кроме того, работает df -h:

Filesystem      Size  Used Avail Use% Mounted on
overlay          30G   21G  7.6G  74% /
tmpfs            64M     0   64M   0% /dev
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
/dev/sda1        30G   21G  7.6G  74% /etc/hosts
tmpfs           3.9G     0  3.9G   0% /proc/asound
tmpfs           3.9G     0  3.9G   0% /proc/acpi
tmpfs           3.9G     0  3.9G   0% /proc/scsi
tmpfs           3.9G     0  3.9G   0% /sys/firmware

Итак, я дал вам всю информацию о моей системе. Моей команде g cc не хватает памяти при компиляции большого кода C:

gcc -Os $(python3-config --cflags --ldflags) CCODE.c -o EXECUTABLE_CODE 

cc1: out of memory allocating 66660800 bytes after a total of 290631680 bytes

Запуск только команды gcc (без docker) в RPi4 (4 ГБ ОЗУ), она работает (в то время как на RPi3b +, 1 ГБ ОЗУ он не сообщает о cc1: out of memory). Однако мне нужен RPi3, у которого, к сожалению, другая ОС. Я застрял в этой проблеме на несколько недель. У кого-нибудь есть какие-то советы или разные решения? Спасибо за совет.

1 Ответ

1 голос
/ 16 апреля 2020

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

Для цепочки инструментов вы можете использовать Crosstool-NG . Получение Python для кросс-компиляции - немного больше работы, и я не буду go подробно об этом здесь. Я отошлю вас к Dockerfile и сценариям оболочки , которые я использовал. Вы можете найти больше информации о них здесь .

Для целей этого ответа я собираюсь использовать Docker изображения, которые я построил сам. Они доступны из Docker Hub. Конечно, вы можете создать их самостоятельно, если хотите, исходный код доступен в репозитории GitHub, на который я ссылался ранее. Если вам не нужны NumPy и OpenCV, обязательно закомментируйте все это в Dockerfile, потому что для кросс-компиляции требуется много времени.

Я использовал цепочку инструментов для Linux 4.15 и позже. Если вы используете Raspbian Stretch, его ядро ​​может быть слишком старым. Это должно работать на Raspbian Buster и Ubuntu 18.04 и более поздних версиях. Если вы действительно хотите использовать Stretch, вам нужно отредактировать файл конфигурации цепочки инструментов, как объяснено здесь , и собрать цепочку инструментов самостоятельно. То же самое касается версии Python. По умолчанию используется Python 3.8.2.


1. Подготовьте свой рабочий каталог

Подготовьте папку, содержащую весь код, который вы хотите кросс-компилировать. Если у вас есть внешние зависимости, которые вы можете легко перемещать, поместите их в папку. Позже мы просто смонтируем эту папку в контейнер Docker.

2. Напишите команды сборки в небольшом сценарии оболочки

Создайте файл build-docker.sh, который содержит все команды, которые вы хотите выполнить, в контейнере Docker для создания кода.

set -ex
PY_CONFIG="${RPI_SYSROOT}/usr/local/bin/python3.8-config"
OPTS=$(${PY_CONFIG} --cflags --ldflags)
CC=${HOST_TRIPLE}-gcc
${CC} ${OPTS} CCODE.c -o EXECUTABLE_CODE

Примечание как я использовал скрипт python3.8-config в папке sys root Raspberry Pi. Если вы просто используете python3.8-config без указания полного пути, он будет использовать конфигурацию установки Python на сборочной машине, а это не то, что вам нужно.

Вам также нужно указать кросс-компилятор. Опять же, если вы просто напишите gcc, он использует собственный компилятор x86_64 системы сборки. Вам нужен кросс-компилятор ARM.

3. Запустите скрипт в Docker контейнере

Ваш рабочий каталог должен выглядеть следующим образом:

.
├── build-docker.sh
└── CCODE.c

Теперь мы запустим контейнер Docker с необходимыми инструментами кросс-компиляции , смонтируйте в нем рабочий каталог, чтобы вы могли получить доступ к своему CCODE.c и запустите команды сборки в только что написанном нами скрипте.

docker run \
    --rm \
    -it \
    -v "$PWD:/tmp/workdir" \
    -w "/tmp/workdir" \
    tttapa/rpi-cross:armv8-rpi3-linux-gnueabihf \
    "bash" "build-docker.sh"

При первом запуске он вытянет изображение из Docker Hub, так что это займет некоторое время (больше ГиБ).

Когда сборка будет завершена, у вас должен остаться файл EXECUTABLE_CODE в вашем рабочем каталоге:

$ file EXECUTABLE_CODE
EXECUTABLE_CODE: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux-armhf.so.3,
for GNU/Linux 4.15.18, with debug_info, not stripped

Более подробный пример вы можете найти здесь: https://github.com/tttapa/RPi-Cpp-Toolchain/tree/master/extra/python/cross-compile-module/spam


Небольшая рекомендация: если вы пишете много кода, который требует взаимодействие между C / C ++ и Python, или код, который включает интерпретатор Python, Pybind11 - отличный инструмент. Он имеет привязки для всех стандартных контейнеров C ++ и типов Python / NumPy / Eigen, он позволяет вызывать код Python из кода C ++, экспортировать функции / структуры / классы C / C ++ в виде Python модулей и обрабатывает всю компиляцию для вы используете CMake: https://github.com/pybind/cmake_example


Редактировать: Если ваш секретный CCODE должен вставлять Python, вы должны связаться с lib python :

https://docs.python.org/3.8/whatsnew/3.8.html#debug -build-использует-то-же-abi-as-release-build

Для встраивания Python в приложение, новая опция --embed должна быть передана в python3-config --libs --embed, чтобы получить -lpython3.8 (свяжите приложение с lib python).

OPTS=$(${PY_CONFIG} --cflags --ldflags --embed)
...