ロゴ ロゴ

IntelのNPUを使ってAI処理をやっていくぞ -画像生成編-

まえがき

皆さん新生活にはなれましたかね?私はそこまで大きく変わらないので相も変わらずおもちゃで遊んだ内容を淡々とブログにします.どうもウグイスです.

さて今回は,NPUを使ってAI処理をやっていくぞの2回目です.今回は画像生成をやっていきます.

具体的は,何とかNPUを使って画像生成ができないかを試した内容を日記のようにつづる内容になっております.

先にネタバレをしますが,最終的にはNPUを使って動かすことには成功しましたが,正直生成に時間がかかる状況でもう少し改善が必要かなといったところです.

というわけで,それでも構わないという方のみ続きをどうぞ.

がいよう

まず今回は大きく分けて2つの方法を試しました.

  1. OpenVino
  2. Intel NPU Acceleration Library

先に2ですが,これは前回の言語モデル編でも使用したライブラリです.これは現在開発中のライブラリで,IntelのNPUをPythonから使うためのライブラリです.

次に1ですが,Intelが作っているCPU,GPU,FPGA,VPUといった複数のハードウェアに対してほぼ共通の書き方でAI処理を最適化することが可能なツールキット的なやつです.これを使うことでほぼ同じコードで複数のハードウェアアクセラレーションが可能となります.非常に効率が良いツールといえるでしょう.ちなみにNPUは中身的にはVPUらしい.

あとはOpenMLというのもあるらしいですが,それは守備範囲外です.詳しい人がいれば教えてくれ.

ちゃんとNPUで動かせたのは2の方法でした.まあ順番なので1から紹介していきます.

環境

まずは使用した環境から

ONEXPLAYER X1

OS: Windows11 Home

CPU: Intel Core Ultra7 155H

Memory: 32GB

Disk: 2TB

開発はWindowsでやります.一応Ubuntuとかも対応しているのですが,さすがにWindowsを消してUbuntuを入れるとかデュアルブートとかはちょっと嫌だったので,今回はWindowsを使いました.

Python 3.11.8

OpenVino: 2024.0.0

intel-npu-acceleration-library: 1.0.0

検証環境としてJyupyterNoteBookをVSCodeから開いて使いました.これめちゃくちゃ使いやすいです.

OpenVinoを使う

まずはOpenVinoを使ってCPUを使って,画像生成をするチュートリアルからやりました.

以下のURLのチュートリアルをなぞった感じです.

https://docs.openvino.ai/2022.3/notebooks/225-stable-diffusion-text-to-image-with-output.html

まあ,これは動きました.で問題はNPUを使うところです.

まず,推論パイプラインの構成という部分でモデルのコンパイルをしています.そこで,”AUTO”となっているところにCPUとかNPUとか指定すれば,対象の状態でコンパイルされます.

そこで,全部やろうとしたんですが,テキストエンコーダー部分しか変換できませんでした.

テキストエンコーダーは最初プロンプトを変換するのに使うみたいです.なのでこれで動かすと,初手でちょっとNPUが動いて,あとはCPUでしか作業が行われません.これではNPUで作った画像とは言いづらいのでこれは,失敗だと思います.

もしかしたらいい方法があったかもしれないですが,とにかくこの方法は一度諦めてほかの方法を探ることにしました.では次

Intel NPU Acceleration Libraryを使う

前回のブログでは触れませんでしたが,このライブラリでは任意のPytorchのモデルをコンパイルして,NPUで実行することが可能です.サンプルプログラムは以下の通り.

import intel_npu_acceleration_library
optimized_model = intel_npu_acceleration_library.compile(model, dtype=torch.int8)

# Use the model as usual

でまあ,とりあえず書いてみたコードは以下のようになります.

from diffusers import StableDiffusionPipeline, EulerAncestralDiscreteScheduler
import intel_npu_acceleration_library
import torch

# モデルのダウンロードなど
pipe = StableDiffusionPipeline.from_pretrained("お好きなモデルをお使いください").to("cpu")
pipe.safety_checker = None
text_encoder = pipe.text_encoder
text_encoder.eval()
unet = pipe.unet
unet.eval()
vae = pipe.vae
vae.eval()
pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)

# モデルをNPUで使えるように変換
text_encoder = intel_npu_acceleration_library.compile(text_encoder, dtype=torch.float16)
unet = intel_npu_acceleration_library.compile(unet, dtype=torch.float16)
vae = intel_npu_acceleration_library.compile(vae, dtype=torch.float16)

# 画像の生成
pipe(prompt='お好きなプロンプトをお入れください', num_inference_steps=25).images[0]

このプログラムを動かしたときの,使用率は以下の画像のような感じです.NPUの使用率が最大で20%程度なのでかなり遊んでいることがわかると思います.

一応動いてはいますが,NPUの処理能力は余ってるし,生成に3分くらいかかるので,実用ではないよねといったところです.

あとがき

というわけで,今回はNPUを使ってStableDiffusionを動かしました.

結論から言えば遅すぎて実用ではありません.もう少し何とかならないか調べてみようとは思いますが,まあ無理ではないかと思います.

一応,複数のデバイスを使ってどうこうするのもありますが,それってNPU使って画像生成したといえない気がしますし,難しいところです.

ここまでご精読ありがとうございます.また次回お会いしましょう.

コメント入力

関連サイト