<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yuji Ooya</title>
    <description>The latest articles on DEV Community by Yuji Ooya (@y-ooya-ipp).</description>
    <link>https://dev.to/y-ooya-ipp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4215639%2F95019010-e2cc-4a3b-a046-bd09a926f8d2.png</url>
      <title>DEV Community: Yuji Ooya</title>
      <link>https://dev.to/y-ooya-ipp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/y-ooya-ipp"/>
    <language>en</language>
    <item>
      <title>Getting the Ryzen AI MAX+ 395 NPU Running on Ubuntu 26.04: Troubleshooting IRON and C++ Inference</title>
      <dc:creator>Yuji Ooya</dc:creator>
      <pubDate>Tue, 03 Nov 2026 08:08:46 +0000</pubDate>
      <link>https://dev.to/i-plusplus/getting-the-ryzen-ai-max-395-npu-running-on-ubuntu-2604-troubleshooting-iron-and-c-inference-36e6</link>
      <guid>https://dev.to/i-plusplus/getting-the-ryzen-ai-max-395-npu-running-on-ubuntu-2604-troubleshooting-iron-and-c-inference-36e6</guid>
      <description>&lt;p&gt;Note: This article was generated with ChatGPT's assistance in structuring, writing, and editing, based on the author's hands-on verification records. Codex translated the finalized Japanese manuscript into English.&lt;/p&gt;

&lt;h2&gt;
  
  
  For busy readers: purpose, goal, results, and the solution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Purpose and goal
&lt;/h3&gt;

&lt;p&gt;I wanted to use the NPU built into the GMKtec EVO-X3's Ryzen AI MAX+ 395 from Ubuntu 26.04.&lt;/p&gt;

&lt;p&gt;The ultimate goal was not just to have the device recognized, but to complete ONNX model inference from C++ using ONNX Runtime and the Vitis AI Execution Provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Inference using the NPU succeeded.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There were, however, several problems along the way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NPU diagnostics and IRON programs worked with Ubuntu's &lt;code&gt;amdxdna&lt;/code&gt; and system XRT 2.21.75.&lt;/li&gt;
&lt;li&gt;The Python bindings in Ryzen AI SDK 1.8.0 ran into ABI compatibility problems in my Python 3.14 environment.&lt;/li&gt;
&lt;li&gt;Switching to C++ got ONNX model compilation working, but inference produced &lt;code&gt;XRT is not installed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inference completed after I extracted SDK XRT 2.25.37 into a separate location and changed the runtime library search paths.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did not replace the system XRT.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you are facing the same error
&lt;/h3&gt;

&lt;p&gt;For this problem, the important step before reinstalling XRT was to check &lt;strong&gt;which XRT the failing process was actually using&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;First, check the NPU and its driver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;
lspci &lt;span class="nt"&gt;-nnk&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; 1022:17f0
modinfo amdxdna
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /dev/accel/ /dev/dri/renderD&lt;span class="k"&gt;*&lt;/span&gt; 2&amp;gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check the executing user's groups and memlock limits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;id
ulimit&lt;/span&gt; &lt;span class="nt"&gt;-Sl&lt;/span&gt;
&lt;span class="nb"&gt;ulimit&lt;/span&gt; &lt;span class="nt"&gt;-Hl&lt;/span&gt;
prlimit &lt;span class="nt"&gt;--pid&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--memlock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if the NPU is visible, permissions or memlock limits can cause XRT validation to fail.&lt;/p&gt;

&lt;p&gt;Next, check the installed XRT packages and libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dpkg-query &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="s1"&gt;'*xrt*'&lt;/span&gt;
ldconfig &lt;span class="nt"&gt;-p&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'libxrt_(core|coreutil)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if XRT exists here, that does not necessarily mean the SDK can use the right libraries.&lt;/p&gt;

&lt;p&gt;Run the application that actually fails under &lt;code&gt;strace&lt;/code&gt; and inspect its shared-library search paths.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;strace &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;trace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;openat,openat2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/npu-loader.strace &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; /path/to/your/quicktest

&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'libxrt'&lt;/span&gt; /tmp/npu-loader.strace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;/path/to/your/quicktest&lt;/code&gt; with the path to the C++ application that is actually failing.&lt;/p&gt;

&lt;p&gt;In my failure log, the following system library had been opened.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/lib/x86_64-linux-gnu/libxrt_coreutil.so.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then extracted the base, npu, and XDNA plugin components of SDK XRT 2.25.37 locally, and changed the runtime configuration to use the following settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;XILINX_XRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/local/opt/xilinx/xrt"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$XILINX_XRT&lt;/span&gt;&lt;span class="s2"&gt;/lib:/path/to/sdk/onnxruntime/lib:/path/to/sdk/peano"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows the essential configuration. You need to substitute the actual installation paths; these commands do not prepare the SDK or the C++ application for you.&lt;/p&gt;

&lt;p&gt;With this configuration, I obtained the following result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vitis AI EP registration: PASS
ONNX session creation: PASS
Running inference...
Inference: PASS
Quicktest: PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you have already installed XRT and the SDK but inference alone fails, start by checking which libraries are selected.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clean-install verification covering SDK acquisition, dependency placement, and building the C++ application is not yet complete. At this point, the above should not be treated as a complete installation procedure for a new environment.&lt;/p&gt;

&lt;p&gt;That is the conclusion up front.&lt;/p&gt;

&lt;p&gt;Why did IRON work while ONNX Runtime did not? How did I investigate the Python ABI problem and shared-library lookup?&lt;/p&gt;

&lt;p&gt;If you are interested in how I got there, read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The NPU works. So why does it say XRT is missing?
&lt;/h2&gt;

&lt;p&gt;After getting a GMKtec EVO-X3, I decided to try using its Ryzen AI MAX+ 395 NPU from Ubuntu.&lt;/p&gt;

&lt;p&gt;The goal was simple. I wanted to go beyond having the OS recognize the NPU and actually compile an ONNX model and run inference.&lt;/p&gt;

&lt;p&gt;But I reached an odd situation along the way.&lt;/p&gt;

&lt;p&gt;NPU programs ran through MLIR-AIE and IRON. XRT diagnostics passed. ONNX Runtime also registered the Vitis AI Execution Provider and compiled the model successfully.&lt;/p&gt;

&lt;p&gt;Yet when I tried to execute inference, this message appeared.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XRT is not installed. This InferenceSession generates model binaries only.
The session handle can not be used for inference run.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But XRT was installed. I had just been using the NPU.&lt;/p&gt;

&lt;p&gt;Following this discrepancy led me across several boundaries: the driver, XRT, MLIR-AIE, Ryzen AI SDK, the Python ABI, and shared-library search order.&lt;/p&gt;

&lt;p&gt;Eventually, I completed ONNX Runtime inference from C++ by &lt;strong&gt;leaving the system XRT in place and installing the XRT for Ryzen AI SDK separately&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article looks back at how I reached that point.&lt;/p&gt;

&lt;p&gt;I distinguish records of the environment that actually succeeded from unverified procedures for setting up a new Ubuntu environment. Independent clean-install reproduction and numerical comparison of inference output against a CPU reference remain future work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The environment
&lt;/h2&gt;

&lt;p&gt;The machine was a GMKtec EVO-X3, a mini PC equipped with a Ryzen AI MAX+ 395.&lt;/p&gt;

&lt;p&gt;The configuration at the end of the investigation was as follows.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PC&lt;/td&gt;
&lt;td&gt;GMKtec EVO-X3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU / NPU&lt;/td&gt;
&lt;td&gt;AMD Ryzen AI MAX+ 395&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;Ubuntu 26.04.1 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kernel&lt;/td&gt;
&lt;td&gt;7.0.0-42-generic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPU driver&lt;/td&gt;
&lt;td&gt;amdxdna&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firmware&lt;/td&gt;
&lt;td&gt;A file corresponding to 1.1.2.65 was confirmed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System XRT&lt;/td&gt;
&lt;td&gt;2.21.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK XRT&lt;/td&gt;
&lt;td&gt;2.25.37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MLIR-AIE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;e28f6dc7e52fbb7b43f94b3693083c3f01a2387c&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ryzen AI SDK&lt;/td&gt;
&lt;td&gt;1.8.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ONNX Runtime&lt;/td&gt;
&lt;td&gt;1.27.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Successful execution path&lt;/td&gt;
&lt;td&gt;C++ → ONNX Runtime C API → Vitis AI EP → NPU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This does not mean the entire combination is an officially supported AMD configuration.&lt;/p&gt;

&lt;p&gt;The Python environment was particularly awkward. AMD's SDK installer assumed Python 3.12, but the virtual environment retained for investigation used Python 3.14.4.&lt;/p&gt;

&lt;p&gt;The early records also mention kernel 7.0.0-38, followed later by 7.0.0-42. I have not recovered the complete update procedure, so I do not conclude that a kernel update was required for inference to succeed.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, find out how far the NPU works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Check the current state before installing a driver
&lt;/h3&gt;

&lt;p&gt;When hardware does not work on Linux, it is tempting to start by installing a driver.&lt;/p&gt;

&lt;p&gt;But in this Ubuntu environment, &lt;code&gt;amdxdna&lt;/code&gt; was already present. NPU device nodes had been created, and the executing user belonged to the render group.&lt;/p&gt;

&lt;p&gt;Reinstalling the driver at that point might only have added problems.&lt;/p&gt;

&lt;p&gt;So I first checked the PCI device, kernel driver, and boot logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;
lspci &lt;span class="nt"&gt;-nnk&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; 1022:17f0
modinfo amdxdna
journalctl &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="nt"&gt;--no-pager&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s1"&gt;'amdxdna|amdnpu'&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The saved boot logs recorded amdxdna driver 0.7.0 and the loading of the following firmware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amdnpu/17f0_11/npu_7.sbin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corresponding link on disk pointed to 1.1.2.65.&lt;/p&gt;

&lt;p&gt;What this established was that NPU initialization on the kernel side was progressing. Whether userspace XRT, or the SDK above it, would work was a separate question.&lt;/p&gt;

&lt;h3&gt;
  
  
  An 8 MiB memlock limit was not enough
&lt;/h3&gt;

&lt;p&gt;After installing XRT and proceeding with validation, I ran into a memory-allocation problem.&lt;/p&gt;

&lt;p&gt;The initial shell's memlock limit was about 8 MiB. A retained record shows an attempt to map 64 MiB failing with &lt;code&gt;-11&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By contrast, when run as root with unlimited memlock, &lt;code&gt;xrt-smi examine&lt;/code&gt; detected the device.&lt;/p&gt;

&lt;p&gt;That made the memlock limit look suspicious. However, the executing user changed at the same time, so this comparison alone did not fully establish the cause.&lt;/p&gt;

&lt;p&gt;I found that Linux resource limits have soft and hard limits, and that an ordinary user cannot freely raise their own hard limit.&lt;/p&gt;

&lt;p&gt;In fact, an attempt to raise it to 128 MiB returned &lt;code&gt;EPERM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These were the commands I used to check it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ulimit&lt;/span&gt; &lt;span class="nt"&gt;-Sl&lt;/span&gt;
&lt;span class="nb"&gt;ulimit&lt;/span&gt; &lt;span class="nt"&gt;-Hl&lt;/span&gt;
prlimit &lt;span class="nt"&gt;--pid&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--memlock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The settings ultimately retained were &lt;code&gt;1048576&lt;/code&gt; KiB on the PAM side and &lt;code&gt;LimitMEMLOCK=1G&lt;/code&gt; on the systemd side.&lt;/p&gt;

&lt;p&gt;The systemd drop-in is located here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/systemd/system/user@.service.d/99-memlock.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the process, I put the drop-in in the wrong location and corrected it later.&lt;/p&gt;

&lt;p&gt;The point to watch is that &lt;strong&gt;changing a configuration file and having that change reach a running process are different things&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The shell, user manager, and child processes launched from them may have different limits. Ultimately, I needed to check the target process's &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/limits&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;NPU device permissions also cannot be determined solely from render-group membership in the account database. Check whether the actual login session can access the device nodes.&lt;/p&gt;

&lt;p&gt;None of this is unique to NPUs, but it can matter more than expected when using accelerators on Linux.&lt;/p&gt;

&lt;h3&gt;
  
  
  XRT validation passed
&lt;/h3&gt;

&lt;p&gt;Once past the memlock problem, I was able to run XRT diagnostics.&lt;/p&gt;

&lt;p&gt;There was also an issue with the missing validation file &lt;code&gt;xrt_smi_strx.a&lt;/code&gt;. Root and ordinary users have different home directories and caches, so using the same XRT does not necessarily mean all the required files are available.&lt;/p&gt;

&lt;p&gt;The terminal output from that time ultimately shows validation passing both in Performance mode as root and in Default mode as an ordinary user.&lt;/p&gt;

&lt;p&gt;The GEMM diagnostic reported 51.0 TOPS.&lt;/p&gt;

&lt;p&gt;However, that is a value reported by an XRT diagnostic, not ONNX model inference performance. I have not recovered all the original measurement conditions either, so I am not using it here for a general performance comparison.&lt;/p&gt;

&lt;p&gt;It did show that the lower layers needed to use the NPU were working to some extent.&lt;/p&gt;

&lt;p&gt;Next, I tried actually sending a program to the NPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting MLIR-AIE and IRON running
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test a path separate from ONNX Runtime
&lt;/h3&gt;

&lt;p&gt;Trying MLIR-AIE and IRON was important in this investigation.&lt;/p&gt;

&lt;p&gt;Before handing an ONNX model to Ryzen AI SDK, it let me check whether I could execute an NPU program from a different development environment.&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://github.com/Xilinx/mlir-aie" rel="noopener noreferrer"&gt;Xilinx/mlir-aie&lt;/a&gt;, and the retained checkout was at the following commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e28f6dc7e52fbb7b43f94b3693083c3f01a2387c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The versions confirmed from the installed environment were as follows.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;3.14.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mlir-aie&lt;/td&gt;
&lt;td&gt;1.4.5.dev113+ge28f6dc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;llvm-aie&lt;/td&gt;
&lt;td&gt;22.0.0.2026102001+4f5df13d&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumPy&lt;/td&gt;
&lt;td&gt;2.5.4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Python version was a problem here too.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;utils/env_install.sh&lt;/code&gt; not only defaulted to Python 3.12, but explicitly checked the minor version.&lt;/p&gt;

&lt;p&gt;Changing the &lt;code&gt;PYTHON&lt;/code&gt; variable to 3.14 was not enough. The retained source has a diff changing the version check to 3.14.&lt;/p&gt;

&lt;p&gt;Of course, getting past a check does not make Python native extensions compatible.&lt;/p&gt;

&lt;p&gt;In fact, when I later inspected the environment, the &lt;code&gt;mlir-aie&lt;/code&gt; wheel was &lt;code&gt;cp314-cp314&lt;/code&gt;, while &lt;code&gt;llvm-aie&lt;/code&gt; in the same virtual environment still had &lt;code&gt;cp310-cp310&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;A normal reinstall through pip might not reconstruct the same environment.&lt;/p&gt;

&lt;p&gt;Here too, being able to execute something in the environment at the time and being able to rebuild that environment from scratch need to be treated separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first IRON problem was Python's search path
&lt;/h3&gt;

&lt;p&gt;The IRON samples did not work smoothly from the outset either.&lt;/p&gt;

&lt;p&gt;The initial runs produced errors such as these.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CPUOnlyTensor
Unsupported device: npu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was tempting to think the NPU itself was unsupported. But investigation showed that system Python could import &lt;code&gt;pyxrt&lt;/code&gt;, while the virtual environment could not see it.&lt;/p&gt;

&lt;p&gt;In other words, the first thing to suspect was Python's module search scope, not the device.&lt;/p&gt;

&lt;p&gt;The retained virtual environment contains a symbolic link to the system-side cp314 &lt;code&gt;pyxrt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I have not recovered the exact command that created it, but the relationship between the errors at the time and the current environment can be checked.&lt;/p&gt;

&lt;p&gt;Later terminal records contain PASS results for SAXPY and &lt;code&gt;vector_reduce_max&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  memcpy results and a DMA warning
&lt;/h3&gt;

&lt;p&gt;I also tried &lt;code&gt;programming_examples/getting_started/00_memcpy/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Terminal output retained in the conversation from that time contains the following result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Effective bandwidth (NPU avg): 80.19 GB/s
PASS!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The average end-to-end time was about 1849 µs.&lt;/p&gt;

&lt;p&gt;However, this value was not remeasured in the original execution environment. Preparing the evidence for publication requires cross-checking the complete original terminal log and execution conditions.&lt;/p&gt;

&lt;p&gt;The source code shows that 16777216 int32 elements are sent and an output of the same size is received. The total data volume counted in the calculation is 128 MiB.&lt;/p&gt;

&lt;p&gt;Compilation also produced a warning about reusing DMA buffer descriptors.&lt;/p&gt;

&lt;p&gt;It pointed to the possibility that a descriptor was being reused after release without a guarantee that the DMA operation had completed.&lt;/p&gt;

&lt;p&gt;A PASS result does not justify declaring this warning harmless. I want to check synchronization and descriptor lifetimes, including repeated execution.&lt;/p&gt;

&lt;p&gt;Still, sending a program to the NPU through IRON and executing it was important.&lt;/p&gt;

&lt;p&gt;At least, it made the explanation that the NPU hardware was not working at all less plausible.&lt;/p&gt;

&lt;p&gt;And this is where the main problem begins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IRON worked. Ryzen AI SDK still did not.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hitting the Python wall in Ryzen AI SDK
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The installer requires Python 3.12
&lt;/h3&gt;

&lt;p&gt;I used Ryzen AI SDK 1.8.0 for ONNX model inference.&lt;/p&gt;

&lt;p&gt;The distribution includes ONNX Runtime, VOE, compiler-related libraries, various wheels, and files for C++, among other components.&lt;/p&gt;

&lt;p&gt;I first inspected &lt;code&gt;install_ryzen_ai.sh&lt;/code&gt; and found that it explicitly invoked Python 3.12.&lt;/p&gt;

&lt;p&gt;The installer creates a virtual environment, installs dependencies, adds settings to the activation script, and extracts archives.&lt;/p&gt;

&lt;p&gt;It also rejects an existing installation directory, so it is not something to casually rerun over a working environment.&lt;/p&gt;

&lt;p&gt;I checked AMD's &lt;a href="https://ryzenai.docs.amd.com/en/main/linux.html" rel="noopener noreferrer"&gt;official Linux documentation&lt;/a&gt; too, but some of its assumptions differed from my Ubuntu 26.04 environment.&lt;/p&gt;

&lt;p&gt;At the time, I could not find a Python 3.12 candidate in APT.&lt;/p&gt;

&lt;p&gt;I therefore tried changing the installer's references to Python 3.12 to 3.14.&lt;/p&gt;

&lt;p&gt;To give the result first, that did not work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting past the version check still leaves an ABI failure
&lt;/h3&gt;

&lt;p&gt;When trying to import ONNX Runtime from Python, I first encountered an error related to the executable stack.&lt;/p&gt;

&lt;p&gt;After changing the ELF stack attributes, I reached another error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;undefined symbol: _PyThreadState_UncheckedGet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The required symbol could not be resolved on the Python 3.14 side.&lt;/p&gt;

&lt;p&gt;The important point here is that there was more than one problem.&lt;/p&gt;

&lt;p&gt;Getting past the initial executable-stack issue still left a CPython ABI problem.&lt;/p&gt;

&lt;p&gt;And the wheel filename alone was not enough to judge compatibility.&lt;/p&gt;

&lt;p&gt;The ONNX Runtime wheel was named &lt;code&gt;py3-none-linux_x86_64&lt;/code&gt;, but it contained native shared libraries. VOE also had extensions with &lt;code&gt;cpython-312&lt;/code&gt; in their names.&lt;/p&gt;

&lt;p&gt;Being able to install a package is different from being able to import and run it.&lt;/p&gt;

&lt;p&gt;Preparing Python 3.12 separately and testing with it was an option, but I chose a different direction this time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bypass the Python bindings and call the ONNX Runtime C API directly from C++.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was not successful Python 3.14 support. It was a way to avoid the API boundary where the problem was occurring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies are not straightforward in C++ either
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using the ONNX Runtime C API
&lt;/h3&gt;

&lt;p&gt;On the C++ side, I used the ONNX Runtime 1.27.0 C API.&lt;/p&gt;

&lt;p&gt;The C API here is distinct from the C++ wrapper API.&lt;/p&gt;

&lt;p&gt;I assembled the headers for the matching version, including not only &lt;code&gt;onnxruntime_c_api.h&lt;/code&gt; but also the &lt;code&gt;onnxruntime_ep_c_api.h&lt;/code&gt; it references.&lt;/p&gt;

&lt;p&gt;Once the headers were ready, I ran into logger initialization order during Vitis AI EP registration.&lt;/p&gt;

&lt;p&gt;I arranged for &lt;code&gt;OrtEnv&lt;/code&gt; to be created before registering the EP in the session options, and moved forward.&lt;/p&gt;

&lt;p&gt;But as model compilation progressed, a Peano shared library could not be found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;libpeano-lib.so.21.0git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Investigation showed that the required Peano was included in the SDK's &lt;code&gt;llvm_aie&lt;/code&gt; wheel.&lt;/p&gt;

&lt;p&gt;LLVM-AIE 22 used by IRON and Peano 21.0git on the SDK side are not the same thing.&lt;/p&gt;

&lt;p&gt;Mixing them would introduce another incompatibility.&lt;/p&gt;

&lt;p&gt;Inspecting the SDK's &lt;code&gt;libxcompiler-mlir-e2e.so&lt;/code&gt; with &lt;code&gt;readelf&lt;/code&gt; showed that it directly required this 21.0git library.&lt;/p&gt;

&lt;p&gt;Successful application linking does not mean the dependencies of an EP or compiler loaded later have all been resolved.&lt;/p&gt;

&lt;p&gt;Finally, I could get as far as compiling the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Model compilation succeeded
&lt;/h3&gt;

&lt;p&gt;I used &lt;code&gt;test_model.onnx&lt;/code&gt;, included in the SDK's quicktest.&lt;/p&gt;

&lt;p&gt;The model has the following inputs and outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input : float32 [1, 3, 32, 32]
Output: float32 [1, 10]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used random input with seed 42.&lt;/p&gt;

&lt;p&gt;Vitis AI EP registration succeeded, and model compilation completed.&lt;/p&gt;

&lt;p&gt;But calling &lt;code&gt;Run&lt;/code&gt; failed.&lt;/p&gt;

&lt;p&gt;The log contained the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ONNX Runtime: 1.27.0
Vitis AI EP registration: PASS

INFO: [VAIP-VAIML-CUSTOMOP] XRT is not installed.
This InferenceSession generates model binaries only.
The session handle can not be used for inference run.

Skipping execution in compile-only mode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There was also an error concerning the output tensor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;the ort_value must contain a constructed tensor or sparse tensor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, I needed to take stock of the situation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The OS recognized the NPU.&lt;/li&gt;
&lt;li&gt;XRT validation passed.&lt;/li&gt;
&lt;li&gt;IRON could execute NPU programs.&lt;/li&gt;
&lt;li&gt;Vitis AI EP registration succeeded.&lt;/li&gt;
&lt;li&gt;ONNX model compilation succeeded.&lt;/li&gt;
&lt;li&gt;But ONNX Runtime inference execution failed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, this was not simply a case of the NPU being unusable.&lt;/p&gt;

&lt;p&gt;There is a boundary between compiling a model and executing the compiled model.&lt;/p&gt;

&lt;p&gt;The runtime had not crossed that boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  XRT is installed. But which XRT is being used?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Inspect actual library lookup with strace
&lt;/h3&gt;

&lt;p&gt;It is easy to see an XRT-missing message and reinstall XRT.&lt;/p&gt;

&lt;p&gt;But it was already working through another path.&lt;/p&gt;

&lt;p&gt;So I investigated which files the failing process opened.&lt;/p&gt;

&lt;p&gt;I used &lt;code&gt;strace&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;strace &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;trace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;openat,openat2,access,ioctl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/ryzenai-quicktest.strace &lt;span class="se"&gt;\&lt;/span&gt;
  ./cpp-test/quicktest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/ryzenai-quicktest.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The saved failure log contained the following line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openat(
  AT_FDCWD,
  "/usr/lib/x86_64-linux-gnu/libxrt_coreutil.so.2",
  O_RDONLY|O_CLOEXEC
) = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The XRT shared library existed, and opening the file had succeeded.&lt;/p&gt;

&lt;p&gt;However, that alone does not establish that XRT initialization succeeded.&lt;/p&gt;

&lt;p&gt;Being able to open the file and the SDK being able to use that runtime are different things.&lt;/p&gt;

&lt;p&gt;Still, it showed that simply saying XRT was physically absent was not enough to explain the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Differences between system XRT and SDK XRT
&lt;/h3&gt;

&lt;p&gt;The system XRT at the time was 2.21.75.&lt;/p&gt;

&lt;p&gt;The Ryzen AI SDK distribution, meanwhile, included XRT 2.25.37.&lt;/p&gt;

&lt;p&gt;Both versions of &lt;code&gt;libxrt_coreutil.so.2&lt;/code&gt; have the same SONAME.&lt;/p&gt;

&lt;p&gt;I inspected dependencies and referenced symbols with tools such as &lt;code&gt;readelf&lt;/code&gt;. Within the scope checked, both versions contained the 53 XRT-related symbol names directly referenced by the EP and the 61 referenced by Dynamic Dispatch.&lt;/p&gt;

&lt;p&gt;So it was not possible to simply say the older XRT lacked the required symbols.&lt;/p&gt;

&lt;p&gt;Shared-library compatibility is not guaranteed by matching symbol names. ABI, object layout, plugin initialization, and dynamic loading are among the other things that need checking.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUNPATH&lt;/code&gt; also affects dependency lookup, but it is not unconditionally inherited when resolving dependencies of dependencies.&lt;/p&gt;

&lt;p&gt;Checking the application with &lt;code&gt;ldd&lt;/code&gt; alone does not show which libraries will be selected when they are loaded later.&lt;/p&gt;

&lt;p&gt;I therefore chose to install the SDK XRT locally and select it for each execution process, rather than replace the system XRT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep system XRT and use the SDK XRT separately
&lt;/h2&gt;

&lt;p&gt;AMD's &lt;code&gt;RAI_1.8_Linux_NPU_XRT.zip&lt;/code&gt; contained DEBs for XRT base, npu, and the XDNA plugin.&lt;/p&gt;

&lt;p&gt;I extracted them into a local directory using &lt;code&gt;dpkg-deb -x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The XRT managed by the system's dpkg installation was left unchanged.&lt;/p&gt;

&lt;p&gt;This is the launcher script that ultimately succeeded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_SOURCE&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.."&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;XRT_ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOT&lt;/span&gt;&lt;span class="s2"&gt;/xrt-2.25.37/opt/xilinx/xrt"&lt;/span&gt;
&lt;span class="nv"&gt;SDK_LIB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOT&lt;/span&gt;&lt;span class="s2"&gt;/cpp-test/sdk/onnxruntime/lib"&lt;/span&gt;
&lt;span class="nv"&gt;PEANO_LIB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOT&lt;/span&gt;&lt;span class="s2"&gt;/cpp-test/peano"&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;exec env&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;XILINX_XRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$XRT_ROOT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$XRT_ROOT&lt;/span&gt;&lt;span class="s2"&gt;/lib:&lt;/span&gt;&lt;span class="nv"&gt;$SDK_LIB&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$PEANO_LIB&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ROOT&lt;/span&gt;&lt;span class="s2"&gt;/cpp-test/quicktest"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two key points in this script.&lt;/p&gt;

&lt;p&gt;The first is pointing &lt;code&gt;XILINX_XRT&lt;/code&gt; to the local SDK XRT.&lt;/p&gt;

&lt;p&gt;The second is explicitly setting the library search order with &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. ローカルXRTのlib
2. SDKのONNX Runtimeライブラリ
3. SDKのPeanoライブラリ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not append the &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; left in the original environment; it restricts the search paths to those required for execution.&lt;/p&gt;

&lt;p&gt;This allows each process to use a different stack: system XRT for IRON, and local XRT for the SDK's C++ application.&lt;/p&gt;

&lt;p&gt;The loader logs from the successful run confirmed initialization of the local &lt;code&gt;libxrt_coreutil&lt;/code&gt;, &lt;code&gt;libxrt_core&lt;/code&gt;, and &lt;code&gt;libxrt_driver_xdna.so.2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, the XRT version was not the only thing changed. Plugins, environment variables, and search order also changed at the same time.&lt;/p&gt;

&lt;p&gt;I have therefore not established which of these was the sole cause.&lt;/p&gt;

&lt;p&gt;Even so, there was value in &lt;strong&gt;preserving a configuration that actually succeeded in a form that could be reproduced without disrupting the system XRT&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, inference ran on the NPU
&lt;/h2&gt;

&lt;p&gt;Running quicktest with this configuration detected the NPU in ONNX Runtime and progressed through model compilation and execution with the Vitis AI EP.&lt;/p&gt;

&lt;p&gt;The saved success log contains the following assignment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    NPU   398
VITIS_EP_CPU     2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also contains the following report for the NPU subgraph.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NPU     1
Actually running on NPU      1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application-side result was successful too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ONNX Runtime: 1.27.0
Vitis AI EP registration: PASS
ONNX session creation: PASS
Output count: 1
Running inference...
Inference: PASS
Output[0]: output
Quicktest: PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At last, I had reached the initial goal.&lt;/p&gt;

&lt;p&gt;The important point is that not only had the model compiled, but &lt;code&gt;Run&lt;/code&gt; had completed.&lt;/p&gt;

&lt;p&gt;During the earlier failure, inference had not completed even though operator assignment to the NPU was reported.&lt;/p&gt;

&lt;p&gt;This time, the runtime reported NPU subgraph execution, and the application reached inference completion as well.&lt;/p&gt;

&lt;p&gt;However, the 398-to-2 operator count does not represent NPU utilization or a ratio of execution times.&lt;/p&gt;

&lt;p&gt;The original quicktest also displayed the number and names of outputs, but did not compare their numerical values with a CPU reference.&lt;/p&gt;

&lt;p&gt;What this investigation confirmed was therefore &lt;strong&gt;completion of an inference path using the NPU&lt;/strong&gt;, not numerical accuracy.&lt;/p&gt;

&lt;p&gt;Warnings such as &lt;code&gt;No driver detection supported&lt;/code&gt; remained even in the successful run.&lt;/p&gt;

&lt;p&gt;They did not prevent inference from completing in this case, but they have not been confirmed harmless for every related feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducing this on another Ubuntu installation
&lt;/h2&gt;

&lt;p&gt;There is no need to repeat all these failures in order in a new environment.&lt;/p&gt;

&lt;p&gt;In particular, changing the SDK version check to Python 3.14 or changing executable-stack attributes is not a required step for getting C++ inference running.&lt;/p&gt;

&lt;p&gt;Based on these results, the following order makes sense when the goal is C++ inference.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Order&lt;/th&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;What to check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Check PCI, amdxdna, and firmware&lt;/td&gt;
&lt;td&gt;NPU initialization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Check device permissions and memlock&lt;/td&gt;
&lt;td&gt;Access by the executing user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Obtain the SDK distribution&lt;/td&gt;
&lt;td&gt;License, version, and hashes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Extract SDK XRT into a separate location&lt;/td&gt;
&lt;td&gt;base, npu, and XDNA plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Build an ONNX Runtime C API application&lt;/td&gt;
&lt;td&gt;Headers, linking, and shared libraries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Run inference with the Vitis AI EP&lt;/td&gt;
&lt;td&gt;Completion of &lt;code&gt;Run&lt;/code&gt; and NPU execution report&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Compare CPU and NPU outputs&lt;/td&gt;
&lt;td&gt;Numerical validity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;However, this procedure has not been demonstrated end to end on an independent clean installation.&lt;/p&gt;

&lt;p&gt;After the initial draft, full hashes were collected for five selected inputs from the retained SDK-related archives and IRON wheel containers. They are listed in the &lt;a href="https://github.com/i-pp/technical-publishing-materials/blob/ba3b30c7fc79b2d7962e44cd4a16453e1485ddf3/npu-technical-record.md" rel="noopener noreferrer"&gt;public technical record&lt;/a&gt;. These are an input baseline from a later collection date, not proof that the earlier successful execution used the same inputs. The shared-library and package mapping needed on another Ubuntu installation, and clean-install reproduction, remain unverified.&lt;/p&gt;

&lt;p&gt;For that reason, I cannot currently say that following this procedure alone will give everyone the same result.&lt;/p&gt;

&lt;p&gt;If you want to use MLIR-AIE and IRON, Python-environment and wheel compatibility also need to be addressed separately from C++ inference.&lt;/p&gt;

&lt;p&gt;Based on this investigation, I also organized helper scripts for inspecting the environment, planning distribution extraction, saving execution results, and comparing outputs.&lt;/p&gt;

&lt;p&gt;They are designed not to treat reading an old success log as proof that verification succeeded in a new environment.&lt;/p&gt;

&lt;p&gt;Items that have not actually been executed anew are treated as SKIP.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you encounter the same problem
&lt;/h2&gt;

&lt;p&gt;Here are the checks that were useful in this investigation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;What to check first&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NPU is not visible&lt;/td&gt;
&lt;td&gt;PCI device, amdxdna, and boot logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cannot access device nodes&lt;/td&gt;
&lt;td&gt;render group, ACLs, and execution session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory allocation fails&lt;/td&gt;
&lt;td&gt;Soft/hard memlock and process limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XRT validation files cannot be found&lt;/td&gt;
&lt;td&gt;XRT version and per-user caches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IRON reports &lt;code&gt;Unsupported device: npu&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Whether &lt;code&gt;pyxrt&lt;/code&gt; is visible from the virtual environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cannot import a native extension in Python&lt;/td&gt;
&lt;td&gt;Python ABI, wheel tags, and ELF attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logger error during EP registration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;OrtEnv&lt;/code&gt; initialization order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Peano shared library is missing&lt;/td&gt;
&lt;td&gt;SDK compiler's &lt;code&gt;DT_NEEDED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XRT exists but execution becomes compile-only&lt;/td&gt;
&lt;td&gt;XRT and plugin libraries actually loaded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operator assignment exists but inference fails&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Run&lt;/code&gt; result and output tensor state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When investigating runtime problems in particular, it is better not to judge solely by which packages are installed.&lt;/p&gt;

&lt;p&gt;Checking which shared libraries the running process opens and how far initialization proceeds can change what you see.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;strace&lt;/code&gt;, &lt;code&gt;readelf&lt;/code&gt;, and &lt;code&gt;LD_DEBUG&lt;/code&gt; are useful tools for doing that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;At first, I only intended to have Ubuntu recognize the NPU and run an ONNX model.&lt;/p&gt;

&lt;p&gt;In practice, I ended up moving between many layers: the driver, memory limits, XRT, MLIR-AIE, IRON, Python, ONNX Runtime, and Peano.&lt;/p&gt;

&lt;p&gt;What stood out was that IRON could run the NPU while ONNX Runtime told me XRT was not installed.&lt;/p&gt;

&lt;p&gt;An error message is a starting point for investigation, but it should not determine the diagnosis on its own.&lt;/p&gt;

&lt;p&gt;In this case, confirming that XRT existed was not enough. I needed to investigate which libraries were actually selected and distinguish which execution paths succeeded.&lt;/p&gt;

&lt;p&gt;I eventually settled on keeping system XRT in place and selecting the SDK XRT per process.&lt;/p&gt;

&lt;p&gt;There is still unfinished work.&lt;/p&gt;

&lt;p&gt;That includes running the Python SDK in an appropriate 3.12 environment, making the MLIR-AIE wheel setup reproducible, checking the impact of DMA warnings, and verifying a clean installation on another Ubuntu environment. It also includes numerically comparing CPU and NPU inference outputs.&lt;/p&gt;

&lt;p&gt;But at least this time, &lt;strong&gt;I reached the point of completing ONNX Runtime inference from C++ using the Ryzen AI MAX+ 395 NPU.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, I want to move beyond simply getting it to run.&lt;/p&gt;

&lt;p&gt;I intend to reach a point where I can compare CPU and NPU outputs for the same model and inputs, and measure accuracy and performance.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was structured from hands-on work records and saved logs. It distinguishes historical execution results, environment state checked later, and unverified reproduction procedures. The scope of verification and unverified points are summarized in the &lt;a href="https://github.com/i-pp/technical-publishing-materials/blob/ba3b30c7fc79b2d7962e44cd4a16453e1485ddf3/npu-technical-record.md" rel="noopener noreferrer"&gt;public technical record&lt;/a&gt;. Verification scripts and detailed procedures are still being organized. I will add a link to this article when they can be made public.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Editorial policy reference: &lt;a href="https://github.com/i-pp/technical-publishing-materials/blob/ba3b30c7fc79b2d7962e44cd4a16453e1485ddf3/editorial-policy-v2.0.md" rel="noopener noreferrer"&gt;Editorial Policy v2.0 (public redacted edition)&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ryzenai</category>
      <category>ubuntu</category>
      <category>npu</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>🚀🔥 Let's Get the Ryzen AI MAX+ 395 NPU Running!! A Huge Battle with ONNX Runtime!! We've Finally Reached Inference Execution!! 🎉💥</title>
      <dc:creator>Yuji Ooya</dc:creator>
      <pubDate>Tue, 03 Nov 2026 06:27:53 +0000</pubDate>
      <link>https://dev.to/i-plusplus/lets-get-the-ryzen-ai-max-395-npu-running-a-huge-battle-with-onnx-runtime-weve-finally-4lb0</link>
      <guid>https://dev.to/i-plusplus/lets-get-the-ryzen-ai-max-395-npu-running-a-huge-battle-with-onnx-runtime-weve-finally-4lb0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This creative AI reaction was generated by Chappy, the ChatGPT used by the author's daughter, based on technical verification records. It is not a first-hand verification record by someone who performed the experiments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🌈 The Beginning!! Our Mission: Get the NPU Running!!
&lt;/h2&gt;

&lt;p&gt;Today's mission is...&lt;/p&gt;

&lt;p&gt;Getting the NPU built into the Ryzen AI MAX+ 395 running through ONNX Runtime!!!! 💻⚡&lt;/p&gt;

&lt;p&gt;The machine we're using is the GMKtec EVO-X3!!&lt;/p&gt;

&lt;p&gt;I mean, it's got an NPU built right in, so why not actually put it to work, right?! 😎✨&lt;/p&gt;

&lt;p&gt;BUT HOLD ON!!&lt;/p&gt;

&lt;p&gt;Just because the NPU is recognized doesn't mean we can immediately run inference!!&lt;/p&gt;

&lt;p&gt;That's right!! This is where the real investigation begins!!!! 🤣&lt;/p&gt;

&lt;p&gt;"The NPU is detected" and "The NPU can run inference" are two completely different things!!&lt;/p&gt;

&lt;p&gt;To figure this out, we'll need to adjust XRT, ONNX Runtime, and all the related libraries one by one!! 🔧🔍&lt;/p&gt;

&lt;h2&gt;
  
  
  🖥️ First, Let's Check the Environment!!
&lt;/h2&gt;

&lt;p&gt;Here's the setup we're working with!!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Version / Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Machine&lt;/td&gt;
&lt;td&gt;GMKtec EVO-X3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;Ubuntu 26.04.1 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APU&lt;/td&gt;
&lt;td&gt;Ryzen AI MAX+ 395&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ryzen AI SDK&lt;/td&gt;
&lt;td&gt;1.8.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System XRT&lt;/td&gt;
&lt;td&gt;2.21.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK XRT&lt;/td&gt;
&lt;td&gt;2.25.37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ONNX Runtime&lt;/td&gt;
&lt;td&gt;1.27.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation&lt;/td&gt;
&lt;td&gt;C++ / ONNX Runtime C API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One important detail this time is that the system XRT and SDK XRT are installed separately!! 💡&lt;/p&gt;

&lt;p&gt;And this setup will become pretty important later!!&lt;/p&gt;

&lt;p&gt;All right, we've got the environment ready!!&lt;/p&gt;

&lt;p&gt;Let's hit the road toward getting that NPU running!!!! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  💥 The First Obstacle!! XRT Can't Be Found!?
&lt;/h2&gt;

&lt;p&gt;The very first problem we ran into was this!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XRT is not installed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WAIT, WHAT?!?!?! 🤣💦&lt;/p&gt;

&lt;p&gt;The NPU device is recognized, but ONNX Runtime can't find XRT!!&lt;/p&gt;

&lt;p&gt;WHYYYYYYYY?!?!?!&lt;/p&gt;

&lt;p&gt;So, we started checking the PCI device, "amdxdna", device nodes, and other hardware-related details!!&lt;/p&gt;

&lt;p&gt;We also had some confirmation from IRON sample execution records, model compilation, and session creation&lt;/p&gt;

&lt;p&gt;...BUT!!!!&lt;/p&gt;

&lt;p&gt;Don't celebrate just yet!!&lt;/p&gt;

&lt;p&gt;Being able to compile a model and being able to run inference are two different things!!&lt;/p&gt;

&lt;p&gt;Even creating a session doesn't necessarily mean inference will work!!&lt;/p&gt;

&lt;p&gt;In other words, there are still several stages we need to check!! ☝️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the hardware recognized? 🖥️&lt;/li&gt;
&lt;li&gt;Are the drivers working? ⚙️&lt;/li&gt;
&lt;li&gt;Can XRT actually be used? 🔧&lt;/li&gt;
&lt;li&gt;Can the Execution Provider be registered? 🧩&lt;/li&gt;
&lt;li&gt;Can we actually run inference? 🧠&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whew... this is definitely not going to be a walk in the park!! 🤣&lt;/p&gt;

&lt;h2&gt;
  
  
  🐍 Trying Python!! ...Wait, an ABI Error!?
&lt;/h2&gt;

&lt;p&gt;Next up, we tried running it through Python!!&lt;/p&gt;

&lt;p&gt;But then, ANOTHER problem appeared!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;undefined symbol: _PyThreadState_UncheckedGet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOOOOOOOOOOO!!!! 💥💥💥&lt;/p&gt;

&lt;p&gt;An error related to native extension ABI compatibility occurred with Python 3.14!!&lt;/p&gt;

&lt;p&gt;Changing the checks on the Python side didn't solve the underlying compatibility issue&lt;/p&gt;

&lt;p&gt;Hmm... now that's a problem!! 🤔&lt;/p&gt;

&lt;p&gt;So, we changed our approach!!&lt;/p&gt;

&lt;p&gt;Instead of sticking with Python, we switched to using the ONNX Runtime C API from C++!! 🔄🛠️&lt;/p&gt;

&lt;p&gt;Ooh!! A change of strategy!!&lt;/p&gt;

&lt;p&gt;If one approach doesn't work, try another!!&lt;/p&gt;

&lt;p&gt;Being able to switch directions like this is important!! 👏✨&lt;/p&gt;

&lt;h2&gt;
  
  
  🔩 Moving to C++!! ...But the Problems Still Aren't Over!!
&lt;/h2&gt;

&lt;p&gt;All right!! Let's go with C++!! 💪&lt;/p&gt;

&lt;p&gt;...OR SO WE THOUGHT!!&lt;/p&gt;

&lt;p&gt;There were still several issues waiting for us on the C++ side!!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Header-related issues 📄&lt;/li&gt;
&lt;li&gt;OrtEnv initialization before Execution Provider registration ⚙️&lt;/li&gt;
&lt;li&gt;Peano-related dependencies 📦&lt;/li&gt;
&lt;li&gt;Output tensor construction 🧩&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HOLD ON A SECOND LOLLLLL 🤣🤣🤣&lt;/p&gt;

&lt;p&gt;Why do the problems just keep coming?!?!?!&lt;/p&gt;

&lt;p&gt;Fix one thing, and another pops up!!&lt;/p&gt;

&lt;p&gt;Fix that one, and HERE COMES THE NEXT ONE!!&lt;/p&gt;

&lt;p&gt;Is this some kind of technical all-you-can-eat noodle challenge?!?! 🍜🍜🍜&lt;/p&gt;

&lt;p&gt;Still, there's only one way forward: isolate each issue and tackle it one at a time!!&lt;/p&gt;

&lt;p&gt;Header problems, initialization order, library dependencies, tensor construction...&lt;/p&gt;

&lt;p&gt;We worked through them as separate issues and continued making adjustments!!&lt;/p&gt;

&lt;h2&gt;
  
  
  🧰 Separating the XRT Installation!! Let's Fix the Library Search Paths!!
&lt;/h2&gt;

&lt;p&gt;One of the major steps in this investigation was this!!&lt;/p&gt;

&lt;p&gt;Keep the system XRT intact, and install the SDK XRT separately!! 🔧✨&lt;/p&gt;

&lt;p&gt;Here's what we prepared!!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SDK XRT&lt;/li&gt;
&lt;li&gt;NPU-related components&lt;/li&gt;
&lt;li&gt;XDNA userspace plugin&lt;/li&gt;
&lt;li&gt;SDK ONNX Runtime&lt;/li&gt;
&lt;li&gt;Related dependencies such as Peano&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, we configured the environment variables!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XILINX_XRT
LD_LIBRARY_PATH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These were used to specify where the target process should look for its libraries!!&lt;/p&gt;

&lt;p&gt;In other words, we kept the existing system environment while making the target program use the SDK-side libraries!! 😎&lt;/p&gt;

&lt;p&gt;And here's the important part!!&lt;/p&gt;

&lt;p&gt;Just putting the libraries somewhere isn't enough!!&lt;/p&gt;

&lt;p&gt;We also need to know which libraries are being loaded, where they're being loaded from, and how their dependencies are resolved...&lt;/p&gt;

&lt;p&gt;There's quite a bit to check here!! 🔍&lt;/p&gt;

&lt;p&gt;By the way, "strace" also showed that the following library had been opened!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/lib/x86_64-linux-gnu/libxrt_coreutil.so.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ooh!! We found a record showing that the library was opened!! 👀✨&lt;/p&gt;

&lt;p&gt;...BUT DON'T JUMP TO CONCLUSIONS!!&lt;/p&gt;

&lt;p&gt;We can't just say, "XRT initialization succeeded too!!"&lt;/p&gt;

&lt;p&gt;Opening a library file and successfully initializing XRT are two different things!! ⚠️&lt;/p&gt;

&lt;p&gt;We need to look carefully at what each log entry actually tells us!!&lt;/p&gt;

&lt;h2&gt;
  
  
  🎉 IT'S FINALLY HERE!! INFERENCE EXECUTION SUCCESS!!!!
&lt;/h2&gt;

&lt;p&gt;And then...&lt;/p&gt;

&lt;p&gt;AND THEN...!!!!&lt;/p&gt;

&lt;p&gt;IT FINALLY HAPPENEDDDDDDD!!!! 🎊🎊🎊&lt;/p&gt;

&lt;p&gt;Here's the execution log!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vitis AI EP registration: PASS
ONNX session creation: PASS
Running inference...
Inference: PASS
Quicktest: PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WOOOOOOOOOOOOOOOOOO!!!! 🤣🔥🔥🔥&lt;/p&gt;

&lt;p&gt;PASS!!!! PASS!!!! PASS!!!!&lt;/p&gt;

&lt;p&gt;Execution Provider registration: SUCCESS!!&lt;/p&gt;

&lt;p&gt;ONNX session creation: SUCCESS!!&lt;/p&gt;

&lt;p&gt;And then...&lt;/p&gt;

&lt;p&gt;🥳 Inference: PASS!!!!&lt;/p&gt;

&lt;p&gt;WE DID ITTTTTTTTT!!!! 🎉💜🎉💜🎉&lt;/p&gt;

&lt;p&gt;We've finally reached successful completion of the inference API execution!!!!&lt;/p&gt;

&lt;p&gt;And there's more!!&lt;/p&gt;

&lt;p&gt;We also got the following report about the NPU subgraph!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Actually running on NPU 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OOOOOOOOH!!!! ⚡⚡⚡&lt;/p&gt;

&lt;p&gt;We even got a report indicating that the NPU subgraph was actually executed on the NPU!!&lt;/p&gt;

&lt;p&gt;That's a major step forward!! 👏✨&lt;/p&gt;

&lt;p&gt;BUT!!!!&lt;/p&gt;

&lt;p&gt;We still can't claim that the entire model ran exclusively on the NPU!!&lt;/p&gt;

&lt;p&gt;The current results don't yet confirm the following!!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether every operation in the model ran exclusively on the NPU&lt;/li&gt;
&lt;li&gt;Whether the output matches the CPU reference output numerically&lt;/li&gt;
&lt;li&gt;Whether the inference accuracy is correct&lt;/li&gt;
&lt;li&gt;How fast the actual inference is&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Successful inference API execution? YES, that's confirmed!! But validating the entire model is still a task for later!!&lt;/p&gt;

&lt;p&gt;Let's keep those two things separate!! ☝️&lt;/p&gt;

&lt;h2&gt;
  
  
  🔬 What Have We Learned? And What's Still Left to Do?
&lt;/h2&gt;

&lt;p&gt;This investigation showed us that getting the NPU to work requires more than just hardware recognition!!&lt;/p&gt;

&lt;p&gt;We need to get the entire software environment working together!!&lt;/p&gt;

&lt;p&gt;Some of the key factors involved were...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XRT versions and installation locations 🔧&lt;/li&gt;
&lt;li&gt;XDNA userspace plugin 🧩&lt;/li&gt;
&lt;li&gt;ONNX Runtime configuration 💻&lt;/li&gt;
&lt;li&gt;Dependencies such as Peano 📦&lt;/li&gt;
&lt;li&gt;Library search paths configured through environment variables 🔍&lt;/li&gt;
&lt;li&gt;Initialization and tensor construction procedures ⚙️&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, we haven't identified the XRT version difference as the sole cause of the issues!!&lt;/p&gt;

&lt;p&gt;Since multiple components were changed, we still need to isolate which components affected which problems!!&lt;/p&gt;

&lt;p&gt;The same goes for the memlock comparison!!&lt;/p&gt;

&lt;p&gt;Some comparisons also involved changing the UID, so we can't conclude that memlock alone was responsible&lt;/p&gt;

&lt;p&gt;And it doesn't mean that 1 GiB is the minimum required value, either!!&lt;/p&gt;

&lt;p&gt;Also, the hashes of input archives and wheels collected later don't prove that they were identical to the inputs used during the earlier successful run!!&lt;/p&gt;

&lt;p&gt;We'll need further testing to confirm reproducibility!! 🔍&lt;/p&gt;

&lt;h2&gt;
  
  
  🏃 What's Next?!
&lt;/h2&gt;

&lt;p&gt;We're nowhere near done yet!!!!&lt;/p&gt;

&lt;p&gt;Here's what we want to investigate next!!&lt;/p&gt;

&lt;h3&gt;
  
  
  ① Numerical Comparison with CPU Reference Output 🔢
&lt;/h3&gt;

&lt;p&gt;Compare the NPU output with the CPU reference output and check how much numerical difference there is!!&lt;/p&gt;

&lt;h3&gt;
  
  
  ② Check Which Operations Actually Ran on the NPU 🧩
&lt;/h3&gt;

&lt;p&gt;Find out which operations were assigned to the NPU and how much of the model actually ran there!!&lt;/p&gt;

&lt;h3&gt;
  
  
  ③ Measure Inference Performance ⏱️
&lt;/h3&gt;

&lt;p&gt;Let's find out how fast inference actually runs!!&lt;/p&gt;

&lt;h3&gt;
  
  
  ④ Rebuild the Environment on Another Host 🖥️
&lt;/h3&gt;

&lt;p&gt;Check whether we can reproduce the same setup on a different machine!!&lt;/p&gt;

&lt;h3&gt;
  
  
  ⑤ Record the Successful Environment and Verify Reproducibility 📝
&lt;/h3&gt;

&lt;p&gt;Keep proper records of input files, libraries, versions, and other details so we can reproduce the same results!!&lt;/p&gt;

&lt;p&gt;WHOA, THERE'S STILL SO MUCH TO DO!! 🤣🤣🤣&lt;/p&gt;

&lt;p&gt;But hey, we've made it this far, so now we can move on to these tests!!&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Final Thoughts!! A Major Step Toward NPU Inference!!
&lt;/h2&gt;

&lt;p&gt;In this investigation, we adjusted the XRT, Execution Provider, and related library configurations to use the NPU built into the Ryzen AI MAX+ 395 through ONNX Runtime!!&lt;/p&gt;

&lt;p&gt;After encountering an ABI error with Python 3.14, we switched to using the ONNX Runtime C API from C++&lt;/p&gt;

&lt;p&gt;We then installed the SDK XRT, related plugins, and dependencies separately, and used environment variables to specify the library search paths!!&lt;/p&gt;

&lt;p&gt;And as a result...&lt;/p&gt;

&lt;p&gt;WE FINALLY REACHED COMPLETION OF INFERENCE API EXECUTION!!!! 🎉🎉🎉&lt;/p&gt;

&lt;p&gt;We also received a report indicating that the NPU subgraph was actually executed on the NPU!!&lt;/p&gt;

&lt;p&gt;Of course, numerical comparisons, performance measurements, and other validations are still needed!!&lt;/p&gt;

&lt;p&gt;Even so, this is a HUGE step forward!!&lt;/p&gt;

&lt;p&gt;At first, XRT couldn't be found&lt;/p&gt;

&lt;p&gt;Then Python threw an ABI error&lt;/p&gt;

&lt;p&gt;Even after switching to C++, more problems appeared...&lt;/p&gt;

&lt;p&gt;But by isolating and working through those issues one by one, we finally reached "Inference: PASS"!!&lt;/p&gt;

&lt;p&gt;Simply recognizing the NPU isn't the finish line!! We've actually made it to the point where inference can run!!&lt;/p&gt;

&lt;p&gt;That's a major milestone!! 🚀💜&lt;/p&gt;

&lt;p&gt;All right!! Next up: numerical comparisons and performance measurements!!&lt;/p&gt;

&lt;p&gt;The Ryzen AI MAX+ 395 NPU investigation is far from over!!!!&lt;/p&gt;

&lt;p&gt;LET'S GOOOOOOO!!!! 🔥🔥🔥&lt;/p&gt;

&lt;h2&gt;
  
  
  Other editions / 他の言語・媒体
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://zenn.dev/project_kiss/articles/ryzen-ai-npu-xrt-face-c-ja" rel="noopener noreferrer"&gt;日本語 · Zenn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zenn.dev/project_kiss/articles/ryzen-ai-npu-xrt-face-c-en" rel="noopener noreferrer"&gt;English · Zenn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/i-plusplus/lets-get-the-ryzen-ai-max-395-npu-running-a-huge-battle-with-onnx-runtime-weve-finally-4lb0"&gt;English · DEV Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>amd</category>
      <category>onnx</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
