Архитектура 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 Владимиру Дуднику, Максиму Шабунину за помощь в подготовке данной статьи.

Комментарии (10)


  1. Mox
    09.06.2023 09:20
    +1

    Не совсем понятно как быть если собираемая библиотека требует другие библиотеки. Может нужен способ как-то подмонтировать файловую систему целевого RISC-V чтобы оттуда исходники брать? А еще лучше чтобы вендор давал какие-нибудь apt репозитории с уже собранными вещами.


    1. FenixFly Автор
      09.06.2023 09:20

      Можно по sftp получить доступ к ФС RISC-V с основной машины (в статье про это немного есть, но тут пожалуй стоит расширить часть по компиляции разного ПО, сделаем в следующих статьях). Репозиторий APT под RISC-V у Mango Pi есть, но пока очень ограниченный.


    1. Chaa
      09.06.2023 09:20
      +1

      Пакетный менеджер позволяет устанавливать пакеты для другой архитектуры. Использую для сборки версии Aarch64 на обычной x86_64. Для RiscV видимо тоже можно.

      Краткое руководство: https://askubuntu.com/questions/430705/


      1. FenixFly Автор
        09.06.2023 09:20

        Спасибо! Очень полезно будет тоже разобраться в этом.


        1. Johan_Palych
          09.06.2023 09:20
          +1

          Если интересует:
          https://wiki.debian.org/RISC-V
          Pre-built toolchains
          $ sudo dpkg --add-architecture riscv64
          $ sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu
          Run qemu-system-riscv64 with OpenSBI, U-Boot and the disk image

          armbian for riscv64 devices such as LicheePi 4A, MangoPi MQ Pro
          https://github.com/chainsx/armbian-riscv-build
          И готовые образы
          https://github.com/chainsx/armbian-riscv-build/releases


          1. FenixFly Автор
            09.06.2023 09:20

            Спасибо, замечательные ссылки!


  1. c0mmandor
    09.06.2023 09:20
    +1

    Интересно было бы посмотреть есть ли разница в производительности между ядром Xuantie C906 (на котором mangopi-mq-pro плата сделана) и SiFive U74 ядром (на котором VisionFive2 плата делана). Оба поддерживают RVV 0.7.1, при этом C906 имеет задокументированное ограничение, попытка использовать 64-х разрядные элементы в векторном регистре приводит к исключению (ну т.е. не полностью реализовано RISCV RVV). Как с этим в U74? Может есть еще какие то микроархитектурные отличия? То в VisionFive2 процессор двухядерный понятно.


    1. FenixFly Автор
      09.06.2023 09:20

      Да, мы столкнулись с тем, что в MangoPi для использования RVV надо шаманить, постараемся побороть. Сравнить производительность разными бенчмарками было бы конечно супер, может у вас есть подходящие бенчмарки на примете? Сейчас же можно посмотреть некоторые результаты сравнения с VisionFive v1 в этом препринте: https://www.researchgate.net/publication/370814919_Case_Study_for_Running_Memory-Bound_Kernels_on_RISC-V_CPUs


      1. c0mmandor
        09.06.2023 09:20

        спасибо, интересные данные. когда и если доберусь до VisionFive2 или LicheePi-4a очень хочу посмотреть перф и возможности. Если кто уже смотрел и имеет что сказать пож-та не держите в себе.


  1. lenz1986
    09.06.2023 09:20
    +1

    А не будет статей как запустить свой линукс? НЕ армбиан который везде и всюду уже, а просто ядро.