0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Intel Arrow Lake 内蔵Intel Arc向け llama.cppインストール 備忘録

0
Posted at

概要

Intel Arcを使ってHuggingfaceにある好きなLLMを使用したいのでllama.cppをインストールする。前回の投稿でIPEX-LLM Ollamaを動かすためのSYCL環境はセットアップ済みなので、ここでは足りないoneAI環境とllama.cppをセットアップする。
はじめからセットアップするのならIntel公式サイトを参照のこと。

なお、SYCLとoneAPIについてChatGPTによると…

Tearm note
SYCL The Khronos Groupで策定したC++ベースのGPUプログラミング言語仕様 CUDAに相当する
oneAPI Intelの開発エコプラットフォームの総称 CPU・GPU・FPGAなど異なる計算デバイスを同じコードで扱うことを目標として設計

The Khronos Groupは他にopenCL, openGL, Vulkanなどの仕様を策定しているよう。ちなにみ定期出張でよく行くHillsboro, Oregonの隣のBeavertonが所在らしい。

こんな流れで進める。

  1. GPUドライバ(不足分)インストール
  2. llama.cppのビルド
  3. llama-serverで動作速度計測

1. GPUドライバ(不足分)インストール

1.0 基本ビルド環境

入っていると思うけれど念の為。

sudo apt install -y cmake build-essential git

前回の投稿で入れたopenCL周りの確認

clinfo -l
groups | grep render

結果

Platform #0: Intel(R) OpenCL Graphics
 `-- Device #0: Intel(R) Arc(TM) Graphics
 ihmon adm cdrom sudo dip plugdev users lpadmin ollama render

1.1 oneAPIリポジトリ追加

Intel の oneAPI パッケージを apt から使えるように設定する。

sudo wget -qO /etc/apt/trusted.gpg.d/intel-oneapi.asc \
  https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB

echo "deb https://apt.repos.intel.com/oneapi all main" | \
  sudo tee /etc/apt/sources.list.d/intel-oneapi.list

sudo apt update

1.2 oneAPIコンパイラとoneAPI MKL(Math Kernel Library)をインストール

oneAPIのコンパイラと計算用ライブラリをインストールし、oneAPI環境を読み込む。

sudo apt install -y intel-oneapi-compiler-dpcpp-cpp intel-oneapi-mkl-devel
source /opt/intel/oneapi/setvars.sh --force

2. llama.cppのビルド

2.1 llama.cppをclone

cd ~
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp

2.2 SYCLビルドの設定

CコンパイラをoneAPIに固定しMKLのパスを明示

rm -rf build-sycl
cmake -S . -B build-sycl \
  -DGGML_SYCL=ON \
  -DCMAKE_BUILD_TYPE=Release \
  -DMKL_DIR="$MKLROOT/lib/cmake/mkl" \
  -DCMAKE_C_COMPILER=/opt/intel/oneapi/compiler/2025.3/bin/icx \
  -DCMAKE_CXX_COMPILER=/opt/intel/oneapi/compiler/2025.3/bin/icpx
  • DGGML_SYCL=ON … SYCL backend を有効にする
  • DMKL_DIR … oneMKL の CMake モジュール場所
  • DCMAKE_{C,CXX}_COMPILER … SYCL 対応コンパイラ指定

2.3 ビルド実行

cmake --build build-sycl -j

結果

build-sycl/bin/llama-cli
build-sycl/bin/llama-server

2.4 llama.cpp動作確認

Intel Arcへモデルをオフロードして動かしてみる。
適当なフォルダにGGUFフォーマットのLLM(ここではqwen2.5-coder-7b-instruct-q4_k_m.gguf)を置いておく。
量子化モデルは下記からいただくことが多い。
https://huggingface.co/unsloth

source /opt/intel/oneapi/setvars.sh --force
export ONEAPI_DEVICE_SELECTOR=level_zero:gpu

build-sycl/bin/llama-cli \
  -m ~/Documents/models/qwen2.5-coder-7b-instruct-q4_k_m.gguf \
  -p "Hello world" \
  -n 512 \
  -ngl 99 \
  -c 4096
  • -n… 生成token数
  • -ngl… GPU offload割合(99:完全GPU ~ 0:完全CPU)
  • -c… 最大コンテキスト長

3. llama-serverで動作速度計測

3.1 準備

llama-serverをデフォルトのポート8080で起動する。

source /opt/intel/oneapi/setvars.sh --force
export ONEAPI_DEVICE_SELECTOR=level_zero:gpu
$HOME/llama.cpp/build-sycl/bin/llama-server -m ~/Documents/models/Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf -n 512 -ngl 99 -c 4096 --port 8080

GPUが使われているか確認するのならモニタを別ターミナルで起動しておく。htopはIntel Arcを認識できず使えなかった。

sudo intel_gpu_top

3.2 動作確認と計測

前回の投稿で使用したOllama版をllama.cpp版へ変更したものが下記。llama.cppはopenaiパケージを使用するのでpip install openaiしておくこと。
llm_db_llama.pyで関数を定義する。

import sqlite3
import os
import re
import pandas as pd
import numpy as np
import datetime
from openai import OpenAI    # ollama から openai に変更

# --- Configuration ---
# llama.cpp server のアドレスを指定
client = OpenAI(base_url="http://localhost:8080/v1", api_key="sk-no-key-required")
MODEL = "qwen2.5-coder:7b" # llama.cpp側でロードしているモデルが使われるため、任意でOK

def execute_pandas_logic_from_llm(user_prompt, df=None, history=None, max_retries=1):
    now = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    if history is None:
        history = []

    working_df = df.copy() if df is not None else None
    
    if working_df is not None:
        context_data = f"Target: Modify existing DataFrame 'df'.\nColumns: {working_df.dtypes.to_string()}\nSample:\n{working_df.head(2).to_string()}"
        mode_instruction = "Modify the existing variable 'df'."
    else:
        context_data = "Target: Create a new DataFrame 'df' from scratch."
        mode_instruction = "You must define 'df'."

    system_prompt = f"""
You are a Pandas expert. {mode_instruction}
[Context]
{context_data}
[Rules]
1. Use ENGLISH for all code.
2. Respond ONLY with executable Python code.
3. The final result of the user's request MUST be stored back into the variable 'df'. 
4. Do not include markdown code blocks.
5. If the result is a Series or a single value, convert it back to a DataFrame and assign it to 'df'.
"""

    messages = [{'role': 'system', 'content': system_prompt}]
    messages.extend(history)
    messages.append({'role': 'user', 'content': user_prompt})

    for attempt in range(max_retries + 1):
        # --- llama.cpp (OpenAI互換) へのリクエストに変更 ---
        response = client.chat.completions.create(
            model=MODEL,
            messages=messages,
            temperature=0.0 # コード生成なので決定論的に
        )
        
        # レスポンスの取得形式を変更
        full_content = response.choices[0].message.content
        
        # --- (以下、exec処理やリトライロジックは変更なし) ---
        match = re.search(r"```python\n?(.*?)\n?```", full_content, re.DOTALL | re.IGNORECASE)
        clean_code = match.group(1).strip() if match else full_content.strip()

        local_vars = {"pd": pd, "np": np, "df": working_df, "datetime": datetime}
        try:
            exec(clean_code, local_vars)
            new_df = local_vars.get('df')

            history.append({'role': 'user', 'content': user_prompt})
            history.append({'role': 'assistant', 'content': f"```python\n{clean_code}\n```"})
            
            return new_df, history
            
        except Exception as e:
            error_msg = str(e)
            if attempt < max_retries:
                messages.append({'role': 'assistant', 'content': clean_code})
                messages.append({'role': 'user', 'content': f"Error: {error_msg}\nPlease fix the code."})
            else:
                print("Maximum retries reached.")
                return df, history

jupyterで10回呼び出したときの平均処理時間を計測する。

import time
from llm_db_llama import execute_pandas_logic_from_llm

time_hist = []
for i in range(11):
    timer_start = time.time()
    user_input = "10行3列(列名はcol1, col2, col3)のDataFrameを作成してください。各要素は平均1.0、標準偏差1.0の正規分布から乱数生成してください。乱数のseedは42にしてください。"
    current_df, pandas_history = execute_pandas_logic_from_llm(user_input)
    # display(current_df)
    # print(pandas_history)

    user_input = "current_dfの各行ではなく、各列の平均値を計算してください。"
    current_df, pandas_history = execute_pandas_logic_from_llm(
                user_input, df=current_df, history=pandas_history
            )
    # display(current_df)
    # print(pandas_history)

    timer_end = time.time()
    timer_elapsed = timer_end - timer_start
    print(f"経過時間: {timer_elapsed:.2f}")
    time_hist.append(timer_elapsed)

print(f"平均経過時間: {sum(time_hist[1:])/len(time_hist[1:]):.2f}")

前回のOllamaの結果と比べると2秒ほど悪化している。同じ7BのモデルでもOllamaでPullできるモデルの量子化条件がわからないので単純比較はできないが、目くじらを立てるほどの違いではないだろう。

平均処理時間 使用したOllama
内蔵Intel Arc 140T 13.46 秒 llama.cpp(今回)
内蔵Intel Arc 140T 11.27 秒 IPEX-LLM Ollama
Core Ultra7 255H CPU 45.62 秒 標準Ollama

ネット環境がなく、ディスクリートGPUが搭載できないエッジ環境といった限られた条件で、再帰的に内部でプロンプトを生成しあう制御システムなどで使えそう。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?