🖥️

ゼロから始めるGPUサーバー構築

2025/04/14に公開

はじめに

STAR AIの大倉です。今回は、LLM(大規模言語モデル)を活用した機能開発にあたり、GPUサーバーを構築する必要があったため、その手順を備忘録としてまとめました。AWSのGPUインスタンスを使い、LLMが動作可能な開発環境をゼロから構築する流れをご紹介します。モデルのサイズや使用用途によって求められるGPU性能は異なりますが、本記事の手順で多くのケースに対応できるはずです。

必要な環境(構築時に選定が必要な項目)

ここでは、LLMを動作させるために必要な環境のうち、特にプロジェクトや利用者ごとに構成が変わるポイントを中心に整理しています。ネットワーク接続やエディタの準備といった基本的な部分は割愛し、それぞれの環境に応じて補っていただければと思います。

1. AWS関連(構築時に選ぶことになる項目)

項目 内容
EC2インスタンスの種類 GPU付き(例:g4dn.2xlarge)を選択。モデルの重さや用途に応じて調整
OSの選択 Ubuntuを推奨(この記事のコマンドはUbuntuを前提に記述)
キーペアの方式 RSA形式で新規作成、または既存の.pemファイルを利用
セキュリティグループ SSH接続(ポート22)や必要に応じたポートの開放設定を行う
Elastic IPの有無 接続を安定させるため、固定IP(Elastic IP)の設定を推奨

2. サーバー内環境(プロジェクトに応じて変わる構成)

項目 内容
Pythonのバージョン 使用するライブラリやモデルに合わせて選定(例:3.8、3.10など)
仮想環境の構築方法 Anaconda推奨(condaでの仮想環境構築)。venvなどでも可
使用ライブラリ MeCab / neologd(日本語処理が必要な場合に導入)
PyTorchのバージョン CUDAやGPUドライバとの互換性を見ながら選定
NVIDIAドライバ 利用するGPU(例:Tesla T4)に適したドライバをインストール(例:nvidia-driver-525
その他必要パッケージ プロジェクトに応じて適宜追加(例:transformersdatasetsなど)

AWSインスタンスの作成

AWSでGPUインスタンスを作成する手順を解説します。インスタンスのタイプやOS、キーペアの設定など、実際に使い始めるまでの基本構成を整えていきます。

1. EC2サーバーにログイン

AWSマネジメントコンソールにログインし、「EC2」サービスを開きます。インスタンスの管理画面から「インスタンスを起動」をクリックします。

2. インスタンス名を入力

インスタンスに任意の名前を設定します。チームで共有する場合は、タスク名や目的がわかりやすい名前にしておくと管理がスムーズです。

3. OSを選ぶ

使用するOSは「Ubuntu」を選びます。本記事の手順はUbuntu環境に基づいています。他のOSを使用する場合は、コマンドの違いに注意してください。

4. インスタンスタイプを選ぶ

LLMの処理にはGPUが必要なため、GPU搭載のインスタンスタイプを選択します。今回は「g4dn.2xlarge」を例にしていますが、モデルのサイズや用途に応じて適宜選択してください。

5. キーペアの作成

SSH接続用のキーペアを作成します。すでにキーペアがある場合はそれを再利用しても問題ありません。新しく作成する場合は以下を参考にしてください。

  • キーペア名:お好きな名前で良いです
  • キーペアタイプ:「RSA」
  • ファイル形式:「.pem」を選択してください

作成した秘密鍵(.pemファイル)は、安全な場所に保管しましょう。

6. ストレージを入力

必要に応じてストレージサイズを指定します。今回は256GiBを設定していますが、用途に応じて変更可能です。ルートボリュームはデフォルト設定のままで問題ありません。

Elastic IPの設定

EC2インスタンスを作成した直後は、接続のたびにパブリックIPアドレスが変更される仕様になっています。これではSSH接続のたびにIPアドレスを確認する手間がかかるため、**Elastic IP(固定IP)**を割り当てて接続を安定させましょう。

1. Elastic IPの管理画面に移動

EC2ダッシュボードの左側メニューから「ネットワーク&セキュリティ」内の「Elastic IP」をクリックし、「Elastic IP の割り当て」ボタンを選択します。設定は基本的にデフォルトのままで問題ありません。「割り当て」ボタンをクリックすれば、Elastic IPが発行されます。

2. IPアドレスを紐づける

取得したElastic IPを選択し、「アクション」メニューから「Elastic IP アドレスの関連付け」を選択します。表示される画面で、先ほど作成したEC2インスタンスを指定し、「関連付け」を実行してください。これで、EC2インスタンスには固定のパブリックIPアドレスが設定され、今後は常に同じIPでアクセスできるようになります。

キーファイルの保存先と権限設定

1. キーファイルの保存先を確認

Macの場合、ファインダーでキーファイル(.pem)を右クリックし、「情報を見る」からパスを確認するか、optionキーを押しながらファイルを右クリックして「パス名をコピー」することで取得できます。

2. 権限の変更コマンドを実行

ターミナルを開き、以下のコマンドでキーファイルの権限を変更します。

chmod 400 (パス)

3. 権限が正しく変更されたか確認

以下のコマンドを入力することで、キーファイルの権限が確認できます。読み取り権限(r)が付与されていることを確認してください。

ls -l /path/to/your-key.pem

表示された結果に -r-------- のような権限が表示されていれば設定完了です。

SSH接続の設定

キーの権限を設定したら、SSH接続の準備を進めましょう。ここでは、VSCodeの「Remote - SSH」拡張を使ってEC2インスタンスへ接続する方法を紹介します。

1. SSH設定ファイルの編集

SSH設定ファイル(~/.ssh/config)を開いた後に、次のような内容を追記してください。

Host <任意の名前>
  HostName <Elastic IPアドレス>
  User ubuntu
  Port <セキュリティのポート範囲>
  IdentityFile <キーの格納パス>
  • HostName には、Elastic IPアドレスを入力します。
  • IdentityFile には、先ほど権限を設定した .pem ファイルのパスを指定します。

2. VSCodeでリモート接続

VSCodeを起動し、「Remote - SSH」拡張機能を使用して、先ほど設定したホスト名(例:aws-llm-server)を選択します。正常に接続できれば、インスタンス上のターミナルが開き、リモートで作業ができるようになります。

Anacondaのインストール(仮想環境構築)

ここでは、LLMの開発環境を整えるために、Anacondaを使用して仮想環境を構築する手順を解説します。

1. ディレクトリの作成

作業ディレクトリを以下のコマンドで作成します。

sudo mkdir /projects/env

2. Anacondaのダウンロード

Anacondaの公式サイト(Download Anaconda Distribution | Anaconda)から、Linux版のインストーラーリンクを取得し、以下のようにインストールします。

bash <取得したパス>

インストール途中で表示される質問には基本的にyesで進めて問題ありません。

3. 仮想環境の作成と有効化

以下のコマンドで仮想環境を作成し、アクティベートします。

conda create -n <仮想環境名> python=<pythonバージョン>
conda activate <仮想環境名>

nvidia-smiのインストール

GPUを活用するには、対応するNVIDIAドライバのインストールが必要です。以下の手順でドライバの導入とGPUの動作確認を行います。

1. 推奨ドライバの確認

推奨されるNVIDIAドライバを確認します。

sudo apt-get update
sudo apt install -y ubuntu-drivers-common
sudo ubuntu-drivers device

以下のような結果が示されるので”recommended”のドライバをインストールするのが良い

== /sys/devices/pci0000:00/0000:00:1e.0 ==
modalias : pci:v000010DEd00001EB8sv000010DEsd000012A2bc03sc02i00
vendor   : NVIDIA Corporation
model    : TU104GL [Tesla T4]
driver   : nvidia-driver-515 - distro non-free
driver   : nvidia-driver-470-server - distro non-free
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-515-server - distro non-free
driver   : nvidia-driver-470 - distro non-free
driver   : nvidia-driver-510 - distro non-free
driver   : nvidia-driver-450-server - distro non-free
driver   : nvidia-driver-525-server - distro non-free
driver   : nvidia-driver-525 - distro non-free recommended ← 推奨バージョン
driver   : xserver-xorg-video-nouveau - distro free builtin

2. ドライバのインストール

表示された推奨バージョン(例:nvidia-driver-525)を以下のようにインストールします。

sudo apt-get install nvidia-driver-525

3. インスタンスの再起動

インストール後、インスタンスを再起動してドライバを有効化します。

sudo systemctl reboot

4. 動作確認(nvidia-smi)

再起動後、以下のコマンドでGPUが正しく認識されているかを確認します。

nvidia-smi

GPUの情報(モデル名、使用率、メモリ使用量など)が表示されれば、ドライバのインストールとGPUの認識に成功しています。

必要ライブラリのインストール

MeCabとPytorchのインストールは注意が必要

1. MeCabのインストール

MeCabを以下コマンドでインストール。入力を求められた場合には全て”y”(Yes)で良い

sudo apt install mecab
sudo apt install libmecab-dev
sudo apt install mecab-ipadic-utf8

2. mecab-ipadic-neologdのインストール

mecab-ipadic-neologdをインストールする。以下コマンドを使用する

git clone https://github.com/neologd/mecab-ipadic-neologd.git
cd mecab-ipadic-neologd
sudo bin/install-mecab-ipadic-neologd

3. Pytorchのインストール

PyTorch から”Your OS”, “Language“, “Compute Platform“を選択してコマンドを取得する

ターミナルに取得したコマンドを入力し”Pytorch”をインストールする

4. その他のインストール

他に必要なものがあればインストールする

pip install (ライブラリ名)

モデルを稼働させる

最後にテストとしてELYZAのLlama3 8Bを読み込んで動かします。

1. モデルの読み込み

最初にモデルを稼働させるためのtokenizerとmodelを読み込みます。

import pandas as pd
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from pathlib import Path
tokenizer = AutoTokenizer.from_pretrained("elyza/Llama-3-ELYZA-JP-8B")
model = AutoModelForCausalLM.from_pretrained(
    "elyza/Llama-3-ELYZA-JP-8B",
    torch_dtype=torch.bfloat16,
    quantization_config=BitsAndBytesConfig(load_in_4bit=True),
    device_map="auto")

2. プロンプト

LLMに聞く内容を入力します。今回は個人的な推し武将、”真田昌幸”の功績を聞いてみます。

messages = [
        {"role": "user", "content": "あなたは歴史に詳しいアシスタントです。真田昌幸の功績を正確に返答してください"}
        ]

3. 出力の制御

メッセージをモデルが理解しやすい形に整え、それをトークンという数値の形式に変換します。その後、モデルに続きを生成させるのですが、その際に「出力の長さ」や「どれくらい創造的にするか」などの細かい設定を行うことで、出力の内容をコントロールしています。

prompt = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
    )
token_ids = tokenizer.encode(
       prompt, add_special_tokens=False,
       return_tensors="pt"
       )
with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        do_sample=True,
        temperature=0.1,
        top_p=0.9,
        max_new_tokens=4096,
        pad_token_id=tokenizer.eos_token_id,
        eos_token_id=tokenizer.eos_token_id,
    )
output = tokenizer.decode(
    output_ids.tolist()[0][token_ids.size(1):],
    skip_special_tokens=True
)
print(output)

4. 結果

真田昌幸(1555年 - 1633年)は、戦国時代から江戸時代初期の武将です。彼の功績は以下の通りです。
真田昌幸は、真田氏の当主として、信濃国(現在の長野県)を中心に活躍しました。彼は、武田信玄、上杉謙信、徳川家康の三者と同盟を結び、各地で合戦を繰り広げました。特に、天正10年(1582年)の「三方ヶ原の戦い」では、徳川家康の軍を破り、家康を一時的に追い詰めるなど、数々の戦功を挙げました。
また、真田昌幸は、戦国時代の有力大名として、領国経営や外交にも長けていました。彼は、信濃国を中心に、上田城や松代城を拠点として、領国を安定化させました。さらに、豊臣秀吉の「小田原征伐」や「関ヶ原の戦い」では、徳川家康や上杉景勝と同盟を結び、秀吉や石田三成の軍に抵抗しました。
真田昌幸は、戦国時代を代表する名将として知られ、真田家の家訓「戦は勝つより負けるなかれ」は、後世の日本の武将や指導者に大きな影響を与えました。

はい、半分くらい嘘ですね。モデルの精度が良ければ正しい返答をしてくれると思いますがLlama3の8Bでは調べものは不向きです。

おわり

以上、LLMを使用するためのGPUサーバー構築手順をご紹介しました。NVIDIAのGPUを搭載したEC2インスタンスを活用することで、LLMの開発・実行環境を効率的に整えることができます。本記事の内容が、同様の環境構築に取り組まれる方の一助となれば幸いです。

参考

Discussion