Кросс-компиляция под RISC-V для самых маленьких

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Архитектура RISC-V корнями уходит к началу 1980-х годов, группа под руководством Дэвида Паттерсона в стенах университета Беркли разработала архитектуры RISC-I и RISC-II. Долгое время архитектуре приходилось существовать в тени лицензируемых ARM и MIPS ядер. Архитектура RISC-V появилась в 2010 году, и поддерживается Linux Foundation. Отметка в 10 миллиардов произведенных ядер была преодолена за 12 лет. 

Сейчас RISC-V может сыграть большую роль в становлении российской микроэлектроники. Компании CloudBEAR и Syntacore  работают над процессорами собственной микроархитектуры, совместимыми с системой команд RISC-V. Архитектура RISC-V позволяет нашим разработчикам создавать энергоэффективные процессоры сравнимого с мировым уровня и сохранять программную совместимость со всеми программами, созданными для экосистемы RISC-V во всем мире. Большая часть RISC-V устройств на сегодняшний день требуют кросс-компилояции кода, чем мы сегодня и займемся.

Исследуемое RISC-V устройство

Нашим подопытным является плата MangoPi MQ PRO D1, выполненная в нестандартном розовом цвете.

Плата размером с Raspberry Pi Zero.
Плата размером с Raspberry Pi Zero.

Характеристики у данной платы следующие:

  • SoC - Allwinner D1 C906 RISC-V частотой 1 ГГц с 2D ускорителем

  • 1 Гб DDR3L ОЗУ (есть версия платы с 512 Мб)

  • Разъем для карты MicroSD под систему

  • Mini HDMI порт

  • 24-контактный разъем для камеры

  • RTL8723DS модуль Wi-Fi 2,4 ГГц 802.11b/g/n + Bluetooth 4.2 и гнездо для антены 

  • 2 USB type C порта под питание и подключение периферии

  • 40-pins GPIO гребенка, идентичная оной на Raspberry Pi

Данная плата стоит чуть больше 2000 рублей на Aliexpress, что делает ее идеальным кандидатом на знакомство с архитектурой RISC-V.

Установка операционной системы на Mango Pi.

Для работы миникомпьютера нужна специализированная сборка операционной системы. Мы возьмем образ системы Armbian 22.08.0-trunk Jammy  c ядром Linux 5.19.0-rc1-d1 с официального сайта mangopi: ссылка. Установка системы делается также, как и на любой Raspberry или его клоне - образ разворачивается на MicroSD карточку, например с помощью Raspberry Pi Imager. Дальше просто вставляем флешку в разъем и подаем питание на плату. Плата начнет загружаться и при подключении mini HDMI к монитору, вы будете видеть логи загрузки.

При первом запуске система предложит установить пароль root-пользователя, а также имя и пароль обычного пользователя. Для подключения WiFi и настройки SSH можно воспользоваться встроенной утилитой armbian-config. В данной утилите с псевдографикой в меню Network можно удобно подключиться к домашней WiFi-сети и включить удаленный доступ по SSH.

С помощью команды ifconfig узнаем ip-адрес нашей MangoPi, чтобы в дальнейшей работать дистанционно.

Установка кросс-компилятора

Сама по себе плата не очень производительная, ведь у нее всего одно процессорное ядро, поэтому для экспериментов наше ПО мы будем собирать с помощью кросс-компилятора на основной машине, и затем запускать на MangoPi. 

Для экспериментов подойдет любая актуальная версия Ubuntu, мы воспользуемся версией 23.04. Для сборки программы под RISC-V архитектуру на x86 машине понадобится собрать и установить кросс-компилятор.

Установим зависимости:

sudo apt-get install git cmake autoconf automake autotools-dev curl \
libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo \
gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build

При установке на Ubuntu 20.04 была небольшая ошибка с установкой пакета libglib2.0-dev, она решилась указанием версии пакета libglib2.0

sudo apt-get install libglib2.0-dev libglib2.0-0=2.64.6-1~ubuntu20.04.3

Скачиваем исходный код кросс-компилятора:

git clone https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain

Создадим директорию под собираемый компилятор:

sudo mkdir -m 777 -p /opt/riscv/bin

И добавим наш будущий компилятор в переменную PATH:

export PATH="/opt/riscv/bin:$PATH"

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

./configure --prefix=/opt/riscv
make linux -j$(nproc)

Сборка кросс-компилятора - дело небыстрое, поэтому запасаемся терпением и кофе, и идем полчаса прогуляться. Возвращаясь с прогулки, видим, что наш компьютер перестал шуметь и переходим к сборке тестовой программы.

#include <stdio.h>
int main()
{
  printf("Hello World\n");
  return 0;
}

Соберем его с помощью нашего кросс-компилятора:

riscv64-unknown-linux-gnu-gcc hello.c -o hello

Чтобы проверить, что мы действительно собрали приложение для архитектуры RISC-V, можно воспользоваться командами readelf или file:

Утилита readelf

$ /opt/riscv/bin/riscv64-unknown-linux-gnu-readelf -h hello
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                         	ELF64
  Data:                          	2s complement, little endian
  Version:                       	1 (current)
  OS/ABI:                        	UNIX - System V
  ABI Version:                   	0
  Type:                          	REL (Relocatable file)
  Machine:                       	RISC-V
  Version:                       	0x1
  Entry point address:           	0x0
  Start of program headers:      	0 (bytes into file)
  Start of section headers:      	848 (bytes into file)
  Flags:                         	0x5, RVC, double-float ABI
  Size of this header:           	64 (bytes)
  Size of program headers:       	0 (bytes)
  Number of program headers:     	0
  Size of section headers:       	64 (bytes)
  Number of section headers:     	12
  Section header string table index: 11

Утилита file

$ file hello
hello: ELF 64-bit LSB relocatable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), not stripped

Для удобства переноса файлов с основной машины на MangoPi можно подключиться по SFTP, тогда файловое пространство MangoPi будет доступной папкой в файловом менеджере, что облегчит копирование.

В Ubuntu подключаем флешку MangoPi как директорию в нашей системе, удобно.
В Ubuntu подключаем флешку MangoPi как директорию в нашей системе, удобно.

Перекинув собранный бинарный файл на MangoPi, программа запустится. Теперь можно переходить к более полезной задаче - кросс-компиляции библиотеки OpenCV под RISC-V.

Кросс-компиляция библиотеки OpenCV для RISC-V

Чтобы узнать возможности платы, давайте соберем под нее OpenCV. Поскольку наша одноядерная плата хорошо вписывается в задачу edge computing - получения изображения с веб-камеры, некоторой обработки и передачи информации, извлеченной из изображений, в хранилище.

Качаем исходный код OpenCV:

git clone https://github.com/opencv/opencv.git
cd opencv

Создаем папку для билда:

mkdir build_mangopi && cd build_mangopi

Собираем OpenCV, гулять уже не идем, потому что OpenCV собирается значительно быстрее.

cmake -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/riscv64-gcc.toolchain.cmake -DCMAKE_C_COMPILER=/opt/riscv/bin/riscv64-unknown-linux-gnu-gcc -DCMAKE_CXX_COMPILER=/opt/riscv/bin/riscv64-unknown-linux-gnu-g++ -DBUILD_SHARED_LIBS=OFF  ../
make -j$(nproc)

В OpenCV собираются несколько тестовых приложений. Перекидываем их на MangoPi и запускаем приложения из папки build_mangopi/bin, собранные с OpenCV. Перенесем файлы из папки build_mangopi/bin на плату и запустим бенчмаркинг модуля core:

build_mangopi/bin/opencv_perf_core

Пришло время кросс-компиляцией собрать собственное приложение, использующее OpenCV. Протестируем скорость работы фильтра Гаусса с большим ядром, повторив запуск фильтра 10 раз. Создадим следующие cpp и cmake файлы.

gaussian.cpp

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat img(2560, 2027, CV_32FC3, Scalar::all(0));
	RNG rng;
	rng.fill(img, RNG::UNIFORM, 0, 255);
	Mat dst;
	TickMeter tick;
	for (size_t i = 0; i < 10; ++i)
	{
    	tick.start();
    	GaussianBlur(img, dst, Size(19, 19), 0.84089642);
    	tick.stop();
    	cout << i << " | " << tick.getAvgTimeMilli() << " ms" << endl;
	}
	return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project( TestGaussian )

find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( TestGaussian gaussian.cpp )
target_link_libraries( TestGaussian ${OpenCV_LIBS} )

Команды для кросс-компиляции нашего приложения с использованием функций OpenCV собранным нами компилятором:

cmake -DCMAKE_TOOLCHAIN_FILE=~/opencv/platforms/linux/riscv64-gcc.toolchain.cmake \
-DCMAKE_C_COMPILER=/opt/riscv/bin/riscv64-unknown-linux-gnu-gcc \
-DCMAKE_CXX_COMPILER=/opt/riscv/bin/riscv64-unknown-linux-gnu-g++ \
-DOpenCV_DIR=~/opencv/build_mangopi -DCMAKE_EXE_LINKER_FLAGS="-latomic" ../
make -j$(nproc)

После того, как у вас собрался файл TestGaussian, перенесите его на MangoPi, и запустите. На моем устройстве программа выдала следующие результаты работы. Интересно что разброс времени работы от запуска к запуску одного и того же фильтра достигает 5%.

./TestGaussian
0 | 15376.1 ms
1 | 14943.1 ms
2 | 14808.8 ms
3 | 14721.3 ms
4 | 14672.3 ms
5 | 14652.8 ms
6 | 14625.9 ms
7 | 14616.6 ms
8 | 14601.1 ms
9 | 14599.2 ms

Поздравляем! У вас получилось собрать RISC-V кросс-компилятор, библиотеку OpenCV и собственное приложение с её использованием. В следующих статьях мы попробуем углубиться в оптимизацию и ускорение вычислений под RISC-V, чтобы улучшить данный результат.

Большая благодарность инженерам компании YADRO Владимиру Дуднику, Максиму Шабунину за помощь в подготовке данной статьи.

Источник: https://habr.com/ru/articles/740868/


Интересные статьи

Интересные статьи

В марте 2023 года OpenStack начал новый цикл обновлений, выпустив Antelope — 27-ю версию облачного стека с открытым исходным кодом. Это первый выпуск в рамках SLURP, где пользователи могут перейти н...
В первой части познакомились с процессором Allwinner D1 на RISC-V архитектуре, рассмотрели возможности, поработали с одноплатным компьютером Sipeed Lichee RV. Старый образ операционной системы сод...
23 мая 1995 года — дата официального выпуска Java. Язык Java и сегодня остается одним из самых востребованных языков программирования в IT. По данным индекса TIOBE, ранжирующего языки программирования...
Всем привет!Разработка для мобильных устройств представляет определённую сложность для авторов приложений - в первую очередь из-за огромного разнообразия в размерах и формах экранов смартфонов и планш...
Дорогие мои друзья, отважные критики, тихие читатели и тайные почитатели, СДСМ заканчивается. Я не могу похвастаться тем, что за 7 лет я затронул все темы сетевой сферы или тем, что хотя б...