Intel環境でLLMを動かす（GPU編）

# はじめに
　IntelのGPUを使ってLLMを動かす際の手順についてまとめました。NPU編は[別項](https://qiita.com/ishikaha/items/41971633192b4ba83f3e)で扱います。
# 使用環境
- AtomMan X7 Ti 185H
- CPU: Intel Core Ultra9 processor 185H
- GPU: Intel Arc Graphics
- Memory: 96GB
- OS: Ubuntu 24.04.1 LTS

# 手順
## ドライバをインストールする
まず、Intelのサイトを参考にドライバをインストールします。

https://dgpu-docs.intel.com/driver/client/overview.html

 ```bash
wget -qO - https://repositories.intel.com/gpu/intel-graphics.key | \
  sudo gpg --yes --dearmor --output /usr/share/keyrings/intel-graphics.gpg
echo "deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/gpu/ubuntu noble client" | \
  sudo tee /etc/apt/sources.list.d/intel-gpu-noble.list
sudo apt update

sudo apt-get install -y libze1 intel-level-zero-gpu intel-opencl-icd clinfo
```
 pytorchで使う以下の2つも入れておきます。
```bash
sudo apt-get install -y libze-dev intel-ocloc
```
 インストールされたか確認します。
 ```bash
 clinfo | grep "Device Name"
 ```
 以下のように表示されれば成功です。
 ```
Device Name                                     Intel(R) Arc(TM) Graphics
　Device Name                                   Intel(R) Arc(TM) Graphics
　Device Name                                   Intel(R) Arc(TM) Graphics
　Device Name                                   Intel(R) Arc(TM) Graphics
```
ついでに、Intel GPU Toolsを入れておきます。GPUの使用状況などを確認できます。
```bash
sudo apt-get install intel-gpu-tools
```

## pytorchなどをインストールする
必要に応じて仮想環境を作成したうえで、以下のサイトを参考にpytorchをインストールします。

https://pytorch.org/docs/stable/notes/get_start_xpu.html

```bash
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/test/xpu
```
xpuが有効かどうかをpythonで確認します。
```python
import torch
torch.xpu.is_available()
```
'True'と出たので大丈夫なようです。


transformersとaccelerateとをインストールします。

```bash
pip install transformers accelerate
```
これで準備は終了です。


# LLMを使ってみる

では実際に動かしてみましょう。例として、tanuki8Bを使ってみます。まず、比較としてGPUを使わないで動かしてみます。

```python
import datetime
from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer

st = datetime.datetime.now()
print("開始時刻", end=": ")
print(st)

model = AutoModelForCausalLM.from_pretrained("weblab-GENIAC/Tanuki-8B-dpo-v1.0", device_map="cpu", torch_dtype="auto")
tokenizer = AutoTokenizer.from_pretrained("weblab-GENIAC/Tanuki-8B-dpo-v1.0")
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

messages = [
    {"role": "system", "content": "以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。"},
    {"role": "user", "content": "たぬきに純粋理性批判は理解できますか？"}
]

input_ids = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device)
output_ids = model.generate(input_ids,
                            max_new_tokens=1024,
                            temperature=0.5,
                            streamer=streamer)

et = datetime.datetime.now()
print("終了時刻", end=": ")
print(et)

t = et - st
print("所要時間", end=": ")
print(t)
```
所要時間は以下のとおりでした。
```bash
所要時間: 0:53:49.054149
```
これは初回なのでモデルのダウンロードにかかる時間が含まれています。もう一度実行してみると、
```bash
所要時間: 0:25:15.120710
```
これがCPUでの実質的な所要時間です。

今度はGPUを使って走らせてみます。上のスクリプトの8行目`device_map="cpu"`を`device_map="xpu"`に修正します。別ウインドウで`sudo intex_gpu_top`を走らせておくとGPUの使用状況がわかります。
```bash
所要時間: 0:05:20.790503
```
所要時間が1/5ほどになりました。だいぶ短くなりました。ただし、Mac Studio(初代・竹)で動かすと52秒程度で終わるので、それに比べるとだいぶ緩慢な気がします。