NPU(XDNA)をプログラムしてみる 環境構築編

NPU

AMD(Xilinx)が提供しているIRONプロジェクトの環境構築を行う。
ほとんど https://github.com/Xilinx/mlir-aie/blob/main/README.md の手順に沿って実行できるが、躓いたところを記載しておく。

環境構築

sudo apt update 
sudo apt install --install-recommends linux-generic-hwe-24.04
sudo reboot

XDNAドライバのインストール

インストールスクリプトを実行するだけでは、XDNAドライバがインストールできなかった。
調べるとXRTのビルドでコケていたいのでオプションを追加して再実行することでインストールできた。

bash ./utils/build_drivers.sh

変更箇所

sudo ./build.sh -npu -opt #これだとエラーになる
sudo ./build.sh -npu -opt -disable-werror

インストールの過程が見れるようにXDNAドライバのインストールスクリプトを修正した。

Install script

#!/bin/bash

echo "Checking kernel version..."
# Check if the kernel version is at least 6.11
KERNEL_VERSION=$(uname -r | cut -d'.' -f1,2)
REQUIRED_VERSION="6.11"

if [[ "$(echo -e "$KERNEL_VERSIONn$REQUIRED_VERSION" | sort -V | head -n1)" != "$REQUIRED_VERSION" ]]; then
    echo "Error: Kernel version must be at least Linux 6.11. Current version: $KERNEL_VERSION"
    exit 1
fi

echo "Cloning the XDNA driver repository..."
# Clone the XDNA driver repository and initialize submodules
XDNA_SHA=deceb066418f2d53fe172a595f59413a731ccee8
git clone https://github.com/amd/xdna-driver.git
export XDNA_SRC_DIR=$(realpath xdna-driver)
cd xdna-driver

echo "Checking out commit $XDNA_SHA..."
git checkout "$XDNA_SHA"
git submodule update --init --recursive

echo "Installing XRT dependencies..."
# Install XRT dependencies
cd "$XDNA_SRC_DIR"
sudo ./tools/amdxdna_deps.sh

echo "Building XRT..."
# Build XRT
cd "$XDNA_SRC_DIR/xrt/build"
#sudo ./build.sh -npu -opt #これだとエラーになる
sudo ./build.sh -npu -opt -disable-werror

echo "Detecting Ubuntu version..."
# Detect Ubuntu version
UBUNTU_VERSION=$(lsb_release -rs)

echo "Ubuntu version detected: $UBUNTU_VERSION"  
echo "Removing any existing XRT and XDNA-driver packages..."
# Find and remove any installed packages that start with "xrt"
packages=$(dpkg -l | awk '/^ii/ && $2 ~ /^xrt/ { print $2 }')
if [ -z "$packages" ]; then
    echo "No packages starting with 'xrt' are installed."
else
    echo "Removing the following packages:"
    echo "$packages"
    sudo apt-get remove -y $packages
fi

echo "Installing new XRT packages..."
# Install XRT packages based on Ubuntu version
cd "$XDNA_SRC_DIR/xrt/build/Release"
case "$UBUNTU_VERSION" in
    "24.04")
        sudo apt reinstall ./xrt_202510.2.19.0_24.04-amd64-base.deb
        sudo apt reinstall ./xrt_202510.2.19.0_24.04-amd64-base-dev.deb
        ;;
    "24.10")
        sudo apt reinstall ./xrt_202510.2.19.0_24.10-amd64-base.deb
        sudo apt reinstall ./xrt_202510.2.19.0_24.10-amd64-base-dev.deb
        ;;
    *)
        echo "Error: Unsupported Ubuntu version ($UBUNTU_VERSION). Supported versions: 24.04, 24.10"
        exit 1
        ;;
esac

echo "Building XDNA Driver..."
# Build XDNA Driver
cd "$XDNA_SRC_DIR/build"
sudo 
./build.sh -release
sudo ./build.sh -package

echo "Installing XDNA plugin..."
# Install XDNA plugin based on Ubuntu version
cd "$XDNA_SRC_DIR/build/Release"
case "$UBUNTU_VERSION" in
    "24.04")
        sudo apt reinstall ./xrt_plugin.2.19.0_ubuntu24.04-x86_64-amdxdna.deb
        ;;
    "24.10")
        sudo apt reinstall ./xrt_plugin.2.19.0_ubuntu24.10-x86_64-amdxdna.deb
        ;;
esac

echo "xdna-driver and XRT built and installed successfully."
echo "Please reboot to apply changes."

NPUを使うためのドライバの読み込み。
NPUを実行するのに毎回実行する必要があるようだ。

source utils/env_setup.sh

結果

System Configuration
  OS Name              : Linux
  Release              : 6.11.0-24-generic
  Machine              : x86_64
  CPU Cores            : 12
  Memory               : 60904 MB
  Distribution         : Ubuntu 24.10
  GLIBC                : 2.40
  Model                : B650I AORUS ULTRA
  BIOS Vendor          : American Megatrends International, LLC.
  BIOS Version         : F22b

XRT
  Version              : 2.19.0
  Branch               : HEAD
  Hash                 : 21c69cbf48f76980b2bff7be8802414f8c1e17c8
  Hash Date            : 2025-04-20 23:34:16
  amdxdna              : 2.19.0_20250420, deceb066418f2d53fe172a595f59413a731ccee8
  virtio-pci           : unknown, unknown
  NPU Firmware Version : 1.5.4.389

Device(s) Present
|BDF             |Name         |
|----------------|-------------|
|[0000:10:00.1]  |NPU Phoenix  |

Ryzen 5 8600Gに実装しているPhoenixのNPUが認識されていることを確認できた。

NPUの動作確認

サンプルのプロジェクトを実行する。今回はNPUでベクトル化した値に整数を加算するサンプルを実行してみる。

cd ../mlir-aie/programming_examples/basic/vector_scalar_add
python3 vector_scalar_add.py npu 
Time taken:  0.00016482699993503047
module {
  aie.device(npu1_1col) {
    %tile_0_2 = aie.tile(0, 2)
    %shim_noc_tile_0_0 = aie.tile(0, 0)
    %mem_tile_0_1 = aie.tile(0, 1)
    aie.objectfifo @in(%shim_noc_tile_0_0, {%mem_tile_0_1}, 2 : i32) : !aie.objectfifo<memref<64xi32>> 
    aie.objectfifo @in_fwd(%mem_tile_0_1, {%tile_0_2}, 2 : i32) : !aie.objectfifo<memref<32xi32>> 
    aie.objectfifo.link [@in] -> [@in_fwd]([] [0])
    aie.objectfifo @out(%tile_0_2, {%mem_tile_0_1}, 2 : i32) : !aie.objectfifo<memref<32xi32>> 
    aie.objectfifo @out_fwd(%mem_tile_0_1, {%shim_noc_tile_0_0}, 2 : i32) : !aie.objectfifo<memref<64xi32>> 
    aie.objectfifo.link [@out] -> [@out_fwd]([] [0])
    %core_0_2 = aie.core(%tile_0_2) {
      %c0 = arith.constant 0 : index
      %c9223372036854775807 = arith.constant 9223372036854775807 : index
      %c1 = arith.constant 1 : index
      scf.for %arg0 = %c0 to %c9223372036854775807 step %c1 {
        %0 = aie.objectfifo.acquire @in_fwd(Consume, 1) : !aie.objectfifosubview<memref<32xi32>>
        %1 = aie.objectfifo.subview.access %0[0] : !aie.objectfifosubview<memref<32xi32>> -> memref<32xi32>
        %2 = aie.objectfifo.acquire @out(Produce, 1) : !aie.objectfifosubview<memref<32xi32>>
        %3 = aie.objectfifo.subview.access %2[0] : !aie.objectfifosubview<memref<32xi32>> -> memref<32xi32>
        %c0_0 = arith.constant 0 : index
        %c32 = arith.constant 32 : index
        %c1_1 = arith.constant 1 : index
        scf.for %arg1 = %c0_0 to %c32 step %c1_1 {
          %4 = memref.load %1[%arg1] : memref<32xi32>
          %c1_i32 = arith.constant 1 : i32
          %5 = arith.addi %4, %c1_i32 : i32
          memref.store %5, %3[%arg1] : memref<32xi32>
        }
        aie.objectfifo.release @in_fwd(Consume, 1)
        aie.objectfifo.release @out(Produce, 1)
      }
      aie.end
    }
    aiex.runtime_sequence @sequence(%arg0: memref<1024xi32>, %arg1: memref<1024xi32>) {
      %0 = aiex.dma_configure_task_for @in {
        aie.dma_bd(%arg0 : memref<1024xi32>, 0, 1024, [<size = 1, stride = 0>, <size = 1, stride = 0>, <size = 1, stride = 0>, <size = 1024, stride = 1>]) {burst_length = 0 : i32}
        aie.end
      }
      aiex.dma_start_task(%0)
      %1 = aiex.dma_configure_task_for @out_fwd {
        aie.dma_bd(%arg1 : memref<1024xi32>, 0, 1024, [<size = 1, stride = 0>, <size = 1, stride = 0>, <size = 1, stride = 0>, <size = 1024, stride = 1>]) {burst_length = 0 : i32}
        aie.end
      } {issue_token = true}
      aiex.dma_start_task(%1)
      aiex.dma_await_task(%1)
      aiex.dma_free_task(%0)
    }
  }
}

計算の様子を可視化したものが以下のようになる。

┌───────────────┐      ┌────────────────────┐

│  Host Memory          │ ---> │ Shim Tile (0,0)              │

└───────────────┘      └─────────┬──────────┘

                                               │  (64xi32)

                                               v

                                        Mem Tile (0,1)

                                              │  (32xi32)

                                              v

                                        AIE Tile (0,2)

                                       (要素に+1演算)

                                              │  (32xi32)

                                              v

                                        Mem Tile (0,1)

                                              │  (64xi32)

                                              v

┌───────────────┐      ┌────────────────────┐

│          Host Memory  │ <--- │ Shim Tile (0,0)             │

└───────────────┘      └────────────────────┘

まとめ

NPUの環境構築を行い、サンプルプログラムを実行することができた。
この記事を書いている間にV0.9からV1.0にバージョンアップしていた。
サンプルのプロジェクトやドライバのインストールに変更がありそうなので、次回はV1.0の環境構築を行ってみる。

タイトルとURLをコピーしました