kWatanabe 記事一覧へ

kWatanabe の 技術帖

某企業でOSや仮想化の研究をやっているインフラ系エンジニア。オンプレとクラウドのコラボレーションなど、興味ある技術を綴る。

LXC非特権コンテナでIntel CPU内蔵GPUを使ってGPGPUする

以前 LXCの非特権コンテナで CUDA する記事を書いた

以前、こんな記事を書いた。

kwatanabe.hatenablog.jp

kWatanabeは、主に waifu2x と ffmpeg を使って動画ファイルを 4K 化するために、LXCゲストでCUDAを動かしている。

github.com

github.com

waifu2xは動画を扱えないので、一度 ffmpegbmp にバラしてから1フレームずつ処理させてるんだけども、そうなるとフレーム同士に依存関係がないので、複数のGPUやCPUを混ぜて並列処理させることができる。

これまで、GeForceとCPUで処理をしていたわけだけど、ふとCPU内蔵GPUも同じように使えるのではと思ったので、試してみた。

検証環境

ホストの設定

GPUの特定と有効化

IntelGPU ドライバは Proxmox VE のカーネルにマージされているので、GeForce のようにドライバを導入する必要はない。

確認する場合は、lspci-v オプションで確認すればよい。まず、PCIのバス番号を調べておいて。

$ lspci | grep VGA
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (rev 06)

バス番号を指定して詳細を確認する。

$ lspci -v -s 00:02.0
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (rev 06) (prog-if 00 [VGA controller])
        Subsystem: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller
        Flags: bus master, fast devsel, latency 0, IRQ 44
        Memory at f7400000 (64-bit, non-prefetchable) [size=4M]
        Memory at e8000000 (64-bit, prefetchable) [size=128M]
        I/O ports at f000 [size=64]
        [virtual] Expansion ROM at 000c0000 [disabled] [size=128K]
        Capabilities: <access denied>
        Kernel driver in use: i915
        Kernel modules: i915

見つからないようなら、GeForce のような dGPU のために iGPU が無効化されていないか、BIOS/UEFI などで確認する。

なお、ここで調べたPCIバス番号 ( 上記の場合は 00:02.0 ) は後で必要なのでメモしておく。

GPUをパススルー

GeForce の時と同様に、/dev/dri 配下をゲストに bind マウントする。素のLXC の場合は config ファイル、Proxmox VE の場合は /etc/pve/lxc 配下の設定ファイルに以下を書き加える。

lxc.cgroup.devices.allow: c 226:* rwm
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir

そして、次がハマりポイント

/dev/dri のファイルは root ユーザ、video グループ、render グループが所有者となっているが、LXCの非特権コンテナの中からは nobodynogroup にリマップされるため、このままで権限不足でアクセスできない。

これを解決するためには以下の2通りの方法がある。

  • LXC がゲストに bind するのをフックして所有者を変更する
  • アクセス権を 660 から 666 に変えてしまう

セキュリティ的にはよくないが、後者の方が簡単。メモしておいた PCI バス番号 ( 今回は 00:02.0 ) を頼りにデバイスファイルのアタリをつける。

$ ls -l /dev/dri/by-path
lrwxrwxrwx 1 root root  8  2月  7 01:06 pci-0000:00:02.0-card -> ../card0
lrwxrwxrwx 1 root root 13  2月  7 01:06 pci-0000:00:02.0-render -> ../renderD128
...

アタリをつけた GPUパーミッションを変更する。

$ sudo chmod 666 /dev/dri/card0 /dev/dri/renderD128

ゲストの設定

まずは、デバイスファイルが bind マウントされており、アクセス権があることを確認する。

$ ls -l /dev/dri        
合計 0
drwxr-xr-x 2 root root         80  2月  7 01:06 by-path/
crw-rw-rw- 1 nobody nogroup 226,   0  2月  7 01:06 card0
crw-rw-rw- 1 nobody nogroup 226, 128  2月  7 01:06 renderD128

問題なければ、実機と同じようにセットアップする。Intel CPU 内蔵 GPU 用の OpenCL ドライバは beignetになる。

$ sudo apt install beignet beignet-opencl-icd opencl-headers clinfo

clinfoOpenCLバイスとして認識できていることを確認する。

$ clinfo -l
Platform #0: Intel Gen OCL Driver
 `-- Device #0: Intel(R) HD Graphics Haswell GT2 Desktop

以上で、LXCの非特権ゲストに Intel CPU 内蔵 GPU をパススルーして、OpenCL できるようになる。

おわりに

  • GeForceをパススルーしてCUDAした以前の記事に引き続き、LXCゲストに Intel CPU 内蔵 GPU をパススルーして OpenCL する方法を整理した
  • バイスファイルのアクセス権の設定を忘れると、デバイスファイルは見えているのに、clinfoからはデバイスが見えないといったことになるので注意
  • waifu2xのように工夫次第で複数、かつ、異種のGPUを使い分けられるワークロードであれば、少しの性能の足しにはなるかもしれない