※上記画像はAMD.com MxGPU公式より引用
GPUの仮想化周りで比較的手軽に触れる技術といえば、「NVIDIA GRID」や「Intel GVT-g」が存在しますが、
AMDでもSR-IOVに対応した「MxGPU」という技術があります。
今回はMxGPUに対応したGPUを入手したのでOpenStack + KVMな環境で仮想GPUリソースを使ってみました。
- AMD MxGPUとは
- Kernelドライバーのインストール
- nova.confの設定(VFを利用する)
- 動作確認
- 参考サイト
1. AMD MxGPUとは
AMDのGPUカード(RADEON , FirePro , Instinct)でSR-IOVの機能を利用して、
1つのGPUを複数の別個の物理デバイスとして認識されるようにできます。
AMD MxGPUを利用したプロダクトとしてはMicrosoft Azureで提供されている、Microsoft Azure® NVv4インスタンスなどがあります。
デバイスとしては非常に扱いやすく、NVIDIA GRIDのように高価なライセンスも不要で、ライセンスコストをかけずにGPUリソースをVMに割り当てることができます。
その上でリモート接続プロトコル(RDPやCitrixやVMware)でVMにアサインしたvGPUをハードウェアアクセラレータとして利用できるので、VDIのパフォーマンス向上を図ることができます。
このように…非常に素晴らしい技術なのですが、難点がいくつかあります。
- 対応カードが非常に限定的で日本国内では入手することが難しい。
- 現行のSR-IOV対応カード(InstinctMi25など)は現時点では仮想GPUとして利用する方法がない。
2020年現在対応カードのマトリックス表は以下の通りです。
GPU | Linux KVM | Citrix Xen | VMware | 備考 |
FirePro S7150 | 〇 | 〇 | 〇 | EoL 型落ちなのでスペックが低い ebayで安い |
FirePro S7150 X2 | 〇 | 〇 | 〇 | EoL 型落ちなのでスペックが低い ebayで安い |
RADEON Pro V340 | × | 〇 | 〇 | 入手すること自体が困難 |
Instinct MI25 | × | × | × | ドライバが対応していない。Azureが使っている |
間違いあればご指摘頂けますと幸いです
今回はFirePro S7150 x2を検証カードとして利用しています。
2.MxGPU用のカーネルモジュール GIMの導入
前項で説明したように、MxGPUとして利用するには対応したカーネルモジュールを導入することが必要です。
Linux KVMの場合はAMDからGIMモジュールが提供されており、そちらを利用することでMxGPUとして利用することができます。
github.com
全てのカードに対応していたら良いのですが…現状はAMD S7150 seriesしか対応していません。
試しにInstinct MI25でも試しましたが、動きませんでした。
GIM導入手順
FirePro S7150 x2がデバイスとして認識されているか確認する
[root@ ~]# lspci -nn |grep AMD b1:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XT GL [FirePro S7150] [1002:6929] b4:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XT GL [FirePro S7150] [1002:6929] # gim導入前はSR-IOVのデバイスは見えてこないので、2つのみ表示される
デフォルトのAMD GPUカーネルモジュールをロードしないようにする。
## blacklist.confの編集 vim /etc/modprobe.d/blacklist.conf ## 内容確認 [root@3 ~]# cat /etc/modprobe.d/nouveau_blacklist.conf blacklist nouveau options nouveau modeset=0 blacklist radeon blacklist amdgpu blacklist amdkfd ## 再起動 # reboot
gimのソースコードをダウンロードとインストール
git clone https://github.com/GPUOpen-LibrariesAndSDKs/MxGPU-Virtualization cd MxGPU-Virtualization/drv/ make make install modprobe gim # modprobe時フリーズするときはLinux Kernelをアップデートすると解決した。 # 当環境は以下の通り [root@~]# uname -r 3.10.0-1127.19.1.el7.x86_64 [root@~]# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core)
SR-IOVデバイスが認識されているか確認する。
#合計32個の仮想VFが認識されていることがわかる。 [root@ ~]# lspci -nn |grep AMD b1:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XT GL [FirePro S7150] [1002:6929] b1:02.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.1 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.2 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.3 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.4 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.5 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.6 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:02.7 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.1 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.2 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.3 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.4 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.5 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.6 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b1:03.7 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XT GL [FirePro S7150] [1002:6929] b4:02.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.1 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.2 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.3 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.4 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.5 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.6 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:02.7 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.1 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.2 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.3 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.4 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.5 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.6 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f] b4:03.7 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Tonga XTV GL [FirePro S7150V] [1002:692f]
OpenStack nova-compute側でFirePro S7150を扱えるようにする。
#alias設定とpassthrough_whiteリストにS7150のカード情報を追加する。 #Vender_IdとProduct_IDはlspciの結果を入れる形となる。nameはnova flavorのプロパティに利用します。 [root@ ~]# vim /etc/nova/nova.conf ......下記を[pci]セクションに追加 # GPU Assign AMD FirePro S7150 x2 MxGPUs alias={"vendor_id":"1002","product_id":"692f","device_type":"type-VF","name":"amdMxGPU_S7150V"} # GPU Assign AMD FirePro S7150 x2 MxGPUs passthrough_whitelist= [{ "name":"amdMxGPU_S7150V" , "vendor_id":"1002", "product_id":"692f" }] ........
# nova-api , scheduler , computeサービスを再起動
novaのflavor情報を追加
GPUリソースを付けたいflavorにextra_specにpci_passthorugh:aliasを下記を参考に追加する。
aliasの値が先ほどnovaに追加したnameになる。
[root@rdo ~(keystone_admin)]# nova flavor-show 6e701757-0bf2-4b47-ad91-6a091735a048 +----------------------------+------------------------------------------------+ | Property | Value | +----------------------------+------------------------------------------------+ | OS-FLV-DISABLED:disabled | False | | OS-FLV-EXT-DATA:ephemeral | 0 | | description | - | | disk | 100 | | extra_specs | {"pci_passthrough:alias": "amdMxGPU_S7150V:1"} | | id | 6e701757-0bf2-4b47-ad91-6a091735a048 | | name | 4Core_8GB_100GB_AMD-MxGPU-S7150 | | os-flavor-access:is_public | True | | ram | 8192 | | rxtx_factor | 1.0 | | swap | | | vcpus | 4 | +----------------------------+------------------------------------------------+
該当flavorを使ってVMを作成すると、MxGPU付きのInstanceが作成される。
3. 動作確認
OpenStack上からVMを作成すると、VFが接続されたVMが作成される。
参考1) Libvirtの定義を見てみる
libvirtのXMLは下記のようになっている。
もしOpenStackなどを用いず手動でlibvirt xmlを定義してVMを作成したい場合は下記をご参照ください。
<domain type='kvm' id='1'> <name>instance-000000cd</name> <uuid>645270f0-b840-4c4b-a4ac-955a6d64ea91</uuid> <metadata> <nova:instance xmlns:nova="http://openstack.org/xmlns/libvirt/nova/1.0"> <nova:package version="17.0.13-1.el7"/> <nova:name>mxgpu-vm</nova:name> <nova:creationTime>2020-10-01 05:13:00</nova:creationTime> <nova:flavor name="4Core_8GB_100GB_AMD-MxGPU-S7150"> <nova:memory>8192</nova:memory> <nova:disk>100</nova:disk> <nova:swap>0</nova:swap> <nova:ephemeral>0</nova:ephemeral> <nova:vcpus>4</nova:vcpus> </nova:flavor> <nova:owner> <nova:user uuid="4cfbced8a22742ee9c0cb85434c5cf1c">admin</nova:user> <nova:project uuid="16d8bbfc828b40109fa6d0b780ccca00">admin</nova:project> </nova:owner> <nova:root type="image" uuid="402ae9f3-e5ee-4ba3-807d-7a69d3fb91a5"/> </nova:instance> </metadata> <memory unit='KiB'>8388608</memory> <currentMemory unit='KiB'>8388608</currentMemory> <vcpu placement='static'>4</vcpu> <cputune> <shares>4096</shares> </cputune> <resource> <partition>/machine</partition> </resource> <sysinfo type='smbios'> <system> <entry name='manufacturer'>RDO</entry> <entry name='product'>OpenStack Compute</entry> <entry name='version'>17.0.13-1.el7</entry> <entry name='serial'>d2647a1e-9ee2-46b4-b9b5-fbd166664f4e</entry> <entry name='uuid'>645270f0-b840-4c4b-a4ac-955a6d64ea91</entry> <entry name='family'>Virtual Machine</entry> </system> </sysinfo> <os> <type arch='x86_64' machine='pc-q35-rhel7.6.0'>hvm</type> <boot dev='hd'/> <smbios mode='sysinfo'/> </os> <features> <acpi/> <apic/> </features> <cpu mode='host-passthrough' check='none'> <topology sockets='4' cores='1' threads='1'/> </cpu> <clock offset='utc'> <timer name='pit' tickpolicy='delay'/> <timer name='rtc' tickpolicy='catchup'/> <timer name='hpet' present='no'/> </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> <devices> <emulator>/usr/libexec/qemu-kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='none'/> <source file='/var/lib/nova/instances/645270f0-b840-4c4b-a4ac-955a6d64ea91/disk'/> <backingStore type='file' index='1'> <format type='raw'/> <source file='/var/lib/nova/instances/_base/5739657f125a79d1b97e7d90950cefac80119a8b'/> <backingStore/> </backingStore> <target dev='vda' bus='virtio'/> <alias name='virtio-disk0'/> <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> </disk> <controller type='usb' index='0' model='qemu-xhci'> <alias name='usb'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> </controller> <controller type='sata' index='0'> <alias name='ide'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> </controller> <controller type='pci' index='0' model='pcie-root'> <alias name='pcie.0'/> </controller> <controller type='pci' index='1' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='1' port='0x10'/> <alias name='pci.1'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/> </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='2' port='0x11'/> <alias name='pci.2'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='3' port='0x12'/> <alias name='pci.3'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> </controller> <controller type='pci' index='4' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='4' port='0x13'/> <alias name='pci.4'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> </controller> <controller type='pci' index='5' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='5' port='0x14'/> <alias name='pci.5'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> </controller> <controller type='pci' index='6' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='6' port='0x15'/> <alias name='pci.6'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> </controller> <interface type='bridge'> <mac address='fa:16:3e:14:3a:4f'/> <source bridge='qbr70911c88-80'/> <target dev='tap70911c88-80'/> <model type='virtio'/> <mtu size='1500'/> <alias name='net0'/> <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </interface> <serial type='pty'> <source path='/dev/pts/1'/> <log file='/var/lib/nova/instances/645270f0-b840-4c4b-a4ac-955a6d64ea91/console.log' append='off'/> <target type='isa-serial' port='0'> <model name='isa-serial'/> </target> <alias name='serial0'/> </serial> <console type='pty' tty='/dev/pts/1'> <source path='/dev/pts/1'/> <log file='/var/lib/nova/instances/645270f0-b840-4c4b-a4ac-955a6d64ea91/console.log' append='off'/> <target type='serial' port='0'/> <alias name='serial0'/> </console> <input type='tablet' bus='usb'> <alias name='input0'/> <address type='usb' bus='0' port='1'/> </input> <input type='mouse' bus='ps2'> <alias name='input1'/> </input> <input type='keyboard' bus='ps2'> <alias name='input2'/> </input> <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0' keymap='ja'> <listen type='address' address='0.0.0.0'/> </graphics> <video> <model type='cirrus' vram='16384' heads='1' primary='yes'/> <alias name='video0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </video> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0000' bus='0xb4' slot='0x03' function='0x7'/> </source> <alias name='hostdev0'/> <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> </hostdev> <memballoon model='virtio'> <stats period='10'/> <alias name='balloon0'/> <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/> </memballoon> </devices> <seclabel type='dynamic' model='dac' relabel='yes'> <label>+107:+107</label> <imagelabel>+107:+107</imagelabel> </seclabel> </domain>
vfioのセクションでnodedevの情報を書いてデバイスを渡してあげている感じですね。
[root@ ~]# virsh nodedev-dumpxml pci_0000_b4_03_7 <device> <name>pci_0000_b4_03_7</name> <path>/sys/devices/pci0000:ae/0000:ae:00.0/0000:af:00.0/0000:b0:10.0/0000:b4:03.7</path> <parent>pci_0000_b0_10_0</parent> <driver> <name>vfio-pci</name> </driver> <capability type='pci'> <domain>0</domain> <bus>180</bus> <slot>3</slot> <function>7</function> <product id='0x692f'>Tonga XTV GL [FirePro S7150V]</product> <vendor id='0x1002'>Advanced Micro Devices, Inc. [AMD/ATI]</vendor> <capability type='phys_function'> <address domain='0x0000' bus='0xb4' slot='0x00' function='0x0'/> </capability> <iommuGroup number='158'> <address domain='0x0000' bus='0xb4' slot='0x03' function='0x7'/> </iommuGroup> <numa node='1'/> <pci-express> <link validity='cap' port='16' speed='8' width='16'/> <link validity='sta' width='0'/> </pci-express> </capability> </device> <iommuGroup number='151'> <address domain='0x0000' bus='0xb4' slot='0x03' function='0x0'/> </iommuGroup> <numa node='1'/> <pci-express> <link validity='cap' port='16' speed='8' width='16'/> <link validity='sta' width='0'/> </pci-express> </capability> </device>
実際のVMからデバイス情報を見てみる
VMにドライバーを当てるとAMD MxGPUとして認識される。
dxdiag(DirectX12が扱えるデバイスとして認識される)
性能
リモート接続の支援用としては問題なく使えます。
DirectXやOpenCL APIを求めるアプリケーションも動くようになります
が、、、GPU自体は何世代も前の物なので性能はお察しです(´・ω・`)
ハイスペックをお求めの方はパススルーするか現行TeslaカードとGRIDライセンスをお買い求めください!
快適に動きます!
MxGPUは非常に素晴らしい技術なので新しいカードでサポートされることを願ってます…(‐人‐)