2011-08-31

Ubuntu 11.04にCUDA開発環境を導入する

特売で買ったHP Z800 には nVidia の Tesla C2050 を2枚差してある。この GPGPU で遊ぶには CUDA の開発環境を導入する必要がある。nVidia が配布している Ubuntu 用の開発環境 CUDA Toolkit 4.0 は Ubuntu 10.10 用であるが、Ubuntu 11.04 にも導入できるのでその方法を紹介する。
CUDA を Ubuntu 11.04 に導入するに際しての問題点は以下の通り。

  • デフォルトでインストールされる X 用のドライバ nouveau と相性が悪い。
  • Ubuntu のソフトウェア更新(apt による upgrade)時のカーネルのバージョンアップへの対処が必要。
  • Ubuntu 11.04 では GCC のバージョンが 4.5 であるが、CUDA は 4.4 を必要とする。

最初の点の nouveau 問題は結構やっかいで、手順を失敗するとシステムが訳のわからない状態になるので注意が必要だ。この問題をさける一番簡単な対処法は GUI 画面で [追加ドライバ] 設定を用いて nVidia のドライバを導入することである。この方法で導入して再起動すると nouveau カーネルモジュールがロードされないはずで、確かめるには以下を実行すればよい。

$ lsmod | grep nouveau

この状態で nVidia が配布している devdriver → toolkit → sdk の順番でインストールすればよいのだが、nVidia 配布の devdriver を使うと、apt-get upgrade のときのカーネルのバージョンアップのたびにドライバを再導入する必要があってわずらわしい。これを解決するために X Updates の PPA を利用して最新の nVidia ドライバを導入することにする。この PPA を用いると、カーネルのバージョンアップの際に nVidia ドライバの再コンパイルも自動的に行ってくれるので世話がない。
以上を勘案した手順は以下の通り。

  1. GUI 画面で [追加ドライバ] を起動し、nVidia の高性能ドライバを導入し再起動する。
  2. ログイン画面(自動ログインしている人はログアウトしてから)で Ctrl-Alt-F1 を押し、テキストコンソール状態にしてログインする。
  3. $ sudo initctl stop gdm
    $ sudo add-apt-repository ppa:ubuntu-x-swat/x-updates
    $ sudo apt-get update
    $ sudo apt-get upgrade
    $ sudo reboot
    
    再起動後、バージョンを確認する。

     

    $ cat /proc/driver/nvidia/version
    NVRM version: NVIDIA UNIX x86_64 Kernel Module  280.13  Wed Jul 27 16:53:56 PDT 2011
    GCC version:  gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)
    
  4. 必要なパッケージをインストールする。
  5. $ sudo apt-get install gcc-4.4 g++-4.4 libxi-dev libxmu-dev freeglut3-dev
    
  6. nVidia 配布の Toolkit とオプションで Tools SDK、そして SDK をインストールする(driver はインストールしない)。
  7. $ sudo sh cudatoolkit_4.0.17_linux_64_ubuntu10.10.run
    $ sudo sh cudatools_4.0.17_linux_64.run
    $ sh gpucomputingsdk_4.0.17_linux.run
    $ sudo vi /etc/ld.so.conf.d/cuda.conf
    /usr/local/cuda/lib64
    /usr/local/cuda/lib
    $ sudo ldconfig
    $ vi ~/.bashrc
    PATH=/usr/local/cuda/bin:$PATH
    
  8. Toolkit が gcc 4.4 を使うように設定する。
  9. $ sudo mkdir /usr/local/cuda/gcc
    $ for a in gcc g++ cpp; do sudo ln -s /usr/bin/$a-4.4 /usr/local/cuda/gcc/$a; done
    $ sudo vi /usr/local/cuda/bin/nvcc.profile
    compiler-bindir = /usr/local/cuda/gcc
  10. SDK をビルドする。
  11. $ cd ~/NVIDIA_GPU_Computing_SDK/C
    $ make
    $ bin/linux/release/driveQuery
    

ただし、6 の make のところで失敗する。これはどうやら SDK のバグ(devdriver が間違った場所にライブラリをインストールしており、SDK がそれに依存している)らしい。以下の方法で回避できる。

$ LPATH=/usr/lib64/nvidia-current make

これを .bashrc にでも入れておくとよいかも。

$ vi ~/.bashrc
export LPATH=/usr/lib64/nvidia-current

References

LPATH の件は: [0000065: /usr/bin/ld: cannot find -lcuda - Mantis]
X-Updates の PPA については以下で知った: [Ubuntu 10.04 に CUDA をインストールした時のメモ - irie めも]
nvcc.profile の設定による GCC 4.4 の利用については: [HDfpga: Install Cuda 4.0 on Ubuntu 11.04]

2012/2/14 追記

CUDA Toolkit 4.1 がリリースされ、Ubuntu 11.04 に正式対応した。CUDA 4.1 へのアップグレードについて書いた記事を参照: Ubuntu 11.04のCUDA開発環境を4.1にアップグレードする

4844329782 CUDA by Example 汎用GPUプログラミング入門
Jason Sanders, Edward Kandrot, 株式会社クイープ
インプレスジャパン 2011-02-14

2011-08-26

RAIDやLVMが設定されたHDを初期化する方法

Linux によるソフトウェアRAIDやLVMは、HD上のパーティションにメタデータという形で設定を書き込む。これによってHDをマシン間で移動したときなどでも設定ファイル無しに復元できることになる。

ただ、このメタデータは明示的に消去しないとHDを再フォーマットしてもそのまま残り続けて、再度のRAIDやLVMの設定に問題を起こすことがある。例えばインストーラがRAIDやLVMパーティションを誤検知してしまい、訳のわからないことが起こることがある。

Ubuntu のインストーラを用いてこのようなHDをリセット(再初期化)する方法を紹介する。起動ディスクとしてはUbuntuデスクトップインストーラまたはサーバインストーラを用いる。

$ sudo apt-get update
$ sudo apt-get install mdadm

Ubuntuサーバインストーラを使う場合はmdadmが入っているので、レスキューモードを選んでシェルに抜けるだけでよい。

では消去を実行しよう。mdadm には--zero-superblockというオプションがあって、これがメタデータを消去してくれる。

$ for a in /dev/sd[ab]?*; do sudo mdadm --zero-superblock $a; done

LVMも設定している場合は、各パーティションの先頭あたりをきれいにすればよい(lvremoveなどを用いたもっとスマートな方法があるはずだが調べるのが面倒だった...)。

$ for a in /dev/sd[ab]?*; do sudo dd if=/dev/zero of=$a bs=1M count=1; done

この方法で重要なのは、パーティション情報を消去する前に行う必要があるということだ。メタデータの場所はパーティションに対して位置が決まっているからである。もしパーティションを初期化してしまった場合、パーティションの分割を覚えているなら同じ分割でパーティションを設定すれば問題ない。覚えていないならメタデータがありそうな場所(あるいはHD全体)を0で埋める方法をとる必要があるだろう。

メタデータの場所

メタデータがパーティションのどこにあるかを調べてみた。以下のようになっている。

  • RAIDでmetadata=0.9の場合: パーティションのお尻から128K〜64Kの範囲で、64Kアラインされている位置から4Kぶん。
  • RAIDでmetadata=1.xの場合、xによって位置が異なる: 1.0はお尻、1.1は頭、1.2は頭から4Kの場所に位置する(アラインについては不明)。
  • LVMのメタデータはパーティションの先頭にある(RAID上のLVMの場合はもちろんRAIDのメタデータの内側)。

References

RAIDのメタデータの位置について: [RAID superblock formats - Linux Raid Wiki]

LVMのメタデータの位置について: [LVM-on-RAID - The Linux Documentation Project]

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (4)

(承前)

sdaをRAIDに参加させる

無事に/dev/md0からブートできただろうか?この時点でsdaは最早使われていない。あとはこのsdaを片肺飛行しているRAIDに加えればおしまいだ。まずsdaのパーティションのraidフラグを立てる。

$ sudo parted /dev/sda
(parted) toggle 2 raid
(parted) toggle 3 raid
(parted) toggle 4 raid
(parted) quit

さていよいよRAIDにsdaを参加させる。

$ sudo mdadm --add /dev/md0 /dev/sda2
$ sudo mdadm --add /dev/md1 /dev/sda3
$ sudo mdadm --add /dev/md2 /dev/sda4

これにより、参加させたsdaの同期が始まる。同期の様子を見るには以下のようにする。

$ watch cat /proc/mdstat

同期が終わったら再起動でもしておく。

$ sudo reboot

この時点では、以前に作った/etc/grub.d/09_raidによるgrubエントリの生成は必要がなくなっている。update-grubによってちゃんと作られるからだ。/etc/grub.d/09_raidを用意した時点ではsdaがマウントされている状態でmd0のブート用のエントリを作ろうとしたのに対し、いまはmd0がマウントされている状態でmd0のブート用のエントリを作ろうとしているからである。ついでにupgradeも行おう。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rm /etc/grub.d/09_raid
$ sudo update-grub
$ sudo update-initramfs -u
$ sudo grub-install /dev/sda
$ sudo grub-install /dev/sdb
$ sudo reboot

以上でゴールが実現できた。

References

検索するといっぱい出てくるが、どれも試すとなかなか最後まで行かない。最も近いところまで行き、内容も参考になったのが以下のページ(英語): [How To Set Up Software RAID1 On A Running System (Incl. GRUB2 Configuration) (Ubuntu 10.04) | HowtoForge - Linux Howtos and Tutorials]

GPTと2048セクタへのアラインについては以下のページが参考になった: [LinuxMania: RAIDボリュームからのブートとパーティション]

その他、以下のページ群から情報をつなぎ合わせて問題が解決した: [Linuxでmdadmを使ったソフトウェアRAIDの構築・管理メモ - nabeの雑記帳], [RAID1 on etch | qos webmaster's blog], [Ubuntu を BeyondRAID 環境へ移行する (1/2) - nigakyのメモ帳]

2011-08-25

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (3)

(承前)

sdbにRAID 1を構成

ソフトウェアRAIDの構築はmdadmコマンドを用いて行う。ログインしてからターミナルを開いてmdadmをインストールする。

$ sudo apt-get update
$ sudo apt-get install mdadm

依存関係によりpostfixがインストールされて何か質問されるので適当に答えておく。

RAID 1というのは2つのHDのうち1つが壊れても大丈夫というものだ。では実際に壊れたときにはどうすればいいのか?新しいHDを挿した状態でmdadmを実行できればいいのだ。このmdadmの実行をDVDでのレスキュー起動で行ってもよいが、1個のHDが壊れた状態でも起動できるようにすればもっと楽である。デフォルトでは壊れた状態では起動できなくなっている(これは壊れて起動した状態でもう1個が壊れると悲惨な状況になるからである)のでこれを修正する。

$ sudo vi /etc/initramfs-tools/conf.d/mdadm
BOOT_DEGRADED=true
$ sudo reboot

再起動後、sdbをsdaと全く同じようにパーティション分けする。

$ sudo parted /dev/sdb
(parted) mktable gpt
(parted) mkpart _ 1mib 2mib
(parted) toggle 1 bios_grub
(parted) mkpart _ 2mib 1gib
(parted) mkpart _ 1gib 3gib
(parted) mkpart _ 32gib 48gib

RAIDにするためにはパーティションのraidフラグを立てる必要がある。

(parted) toggle 2 raid
(parted) toggle 3 raid
(parted) toggle 4 raid
(parted) quit

いよいよRAID 1の作成だ。

$ sudo mdadm --create /dev/md0 --level=1 -n 2 --metadata=0.9 missing /dev/sdb2
$ sudo mdadm --create /dev/md1 --level=1 -n 2 --metadata=0.9 missing /dev/sdb3
$ sudo mdadm --create /dev/md2 --level=1 -n 2 --metadata=0.9 missing /dev/sdb4

ここで--metadataによってメタデータのフォーマットを0.9にしている点に注意してほしい。--metadataを省略すると1.2になるのだが、これでは後々問題が起こる。先回りして言うと、1.2でもほぼ問題なく最終段階まで設定が成功するのだが、apt-get upgradeでカーネルのアップデートが起こるとそれが失敗してしまうと言う致命的な問題が起こる。これはカーネルアップデートの際に実行されるupdate-grubが1.2フォーマットのメタデータを読めないために生じる問題である。ここでメタデータのフォーマットとして0.9を指定しなければならないというのを発見するのにはかなり苦労した。世のページでのソフトウェアRAIDの説明では古いバージョンのmdadmが使われており、その場合メタデータのフォーマット0.9がデフォルトとなるのでうまくいっていたのだ。

ソフトウェアRAIDの状況を確認しておく。

$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md2 : active raid1 sdb4[1]
      16777152 blocks [2/1] [_U]
      
md1 : active raid1 sdb3[1]
      2097088 blocks [2/1] [_U]
      
md0 : active raid1 sdb2[1]
      1046464 blocks [2/1] [_U]
      
unused devices:

パーティションをフォーマットする。

$ sudo mkfs -t ext4 /dev/md0
$ sudo mkfs -t ext4 /dev/md2
$ sudo mkswap /dev/md1

ソフトウェアRAIDの設定を保存する。

$ sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
ARRAY /dev/md0 metadata=0.90 UUID=5f156622:2c294f4b:21de336c:78d7ee00
ARRAY /dev/md1 metadata=0.90 UUID=4e48e1ac:30d9556c:21de336c:78d7ee00
ARRAY /dev/md2 metadata=0.90 UUID=c9e99e19:4bd9a5d8:21de336c:78d7ee00

最近のLinuxでは、このまま再起動すると/dev/md0などの名前が変わってしまうので、初期ラムディスクの作り直しが必要である。

$ sudo update-initramfs -u
$ sudo reboot

再起動して/dev/md0などが存在することを確認する。

/dev/md0からブートできるように設定

fstabを編集して/dev/md?を用いてファイルシステムを組織するように設定する。blkidによって取得したUUIDを用いて/etc/fstabを書き換える。

$ sudo blkid /dev/md[012] | tee /tmp/uuid
/dev/md0: UUID="f45a96a8-8bcf-4a51-9cbe-76c2583ddd5d" TYPE="ext4"
/dev/md1: UUID="1e6eb27a-18d7-4735-9d78-f12c22be17eb" TYPE="swap"
/dev/md2: UUID="a0965d65-1de0-4876-8108-63ef9fe8e568" TYPE="ext4"
$ sudo vi /etc/fstab
UUID=a0965d65-1de0-4876-8108-63ef9fe8e568 /               ext4    noatime,user_xattr,errors=remount-ro  0  1
UUID=f45a96a8-8bcf-4a51-9cbe-76c2583ddd5d /boot           ext4    noatime,user_xattr  0   2
UUID=1e6eb27a-18d7-4735-9d78-f12c22be17eb none            swap    sw              0       0

次に/dev/md0からブートするようにgrubを設定する。

$ cd /etc/grub.d
$ sudo cp 40_custom 09_raid
$ sudo vi 09_raid
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry 'Ubuntu, with Linux 2.6.38-8-generic' --class ubuntu --class gnu-linux --class gnu --class os {
    recordfail
    insmod part_gpt
    insmod raid
    insmod mdraid09
    insmod ext2
    set root='(md0)'
    linux   /vmlinuz-2.6.38-8-generic root=UUID=a0965d65-1de0-4876-8108-63ef9fe8e568 ro   quiet splash vt.handoff=7
    initrd  /initrd.img-2.6.38-8-generic
}
$ sudo update-grub

09_raidファイルの内容は、/boot/grub/grub.cfgからコピーしてきたmenuentryをペーストして変更するとよいだろう。linux行のUUIDにはもちろん先ほどblkidで取得したrootパーティション/dev/md2のものを設定する。

ここの設定も正しいものを探り出すのに大変苦労した。まず、世のページではinsmod mdraidになっているものが多いが、メタデータのフォーマットによってmdraid1xmdraid09を使い分けなければならない。次に大苦労したのが(md0)という表現である。世のページでは(md/0)というのまで出てきて誤植かとも思ったのだが、実はメタデータが1.xのとき(md/0)で、0.9のとき(md0)を使うのだ!そんなことどこに書いてあるんだ!!

初期ラムディスクの再生成を忘れないように。

$ sudo update-initramfs -u

sdaからsdbへのコピー

rsyncの-xオプション(ファイルシステムの境界を越えない指定)を用いてコピーする。

$ sudo mkdir /mnt/md0 /mnt/md2
$ sudo mount /dev/md0 /mnt/md0
$ sudo mount /dev/md2 /mnt/md2
$ sudo rsync -ax / /mnt/md2
$ sudo rsync -ax /boot/ /mnt/md0

5行目の/boot/の終わりのスラッシュを忘れないように。

最後にgrubをインストールして再起動する。片方のHDが壊れてももう片方のHDで起動できるように両方のHDにgrubをインストールする必要がある。

$ sudo grub-install /dev/sda
$ sudo grub-install /dev/sdb
$ sudo reboot

あと一息。

(つづく)

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (2)

(承前)

パーティション分け

2TBを超えるHDでは従前のいわゆるDOSパーティションテーブルは利用できず、GUIDパーティションテーブル(GPT)を使わなくてはならない。今回のHDは2Tなので必ずしもGPTを使う必要はないが、新しく触れる技術なので使ってみたところはまり込んだ次第。

GPTによるパーティション分けはGNU partedというコマンドで行う。Ubuntu デスクトップインストーラで起動し、[Try Ubuntu] を選んでターミナルを開き、parted を実行すればよい。まずはパーティションテーブルの初期化だ(以下を実行するとHDの内容が全部読めなくなるので注意してほしい)。

$ sudo parted /dev/sda
(parted) mktable gpt

さて、説明は省くがGPTを起動ディスクに用いた場合、先頭にbiosgrub属性を持つ1Mのパーティションが必要である。また、Advanced Format Technology (Big Sector) 対応のため、パーティション境界を2048セクタにアラインした方がよいらしい。このためにはセクタ境界の指定にmibまたはgibを用いればいい。以下でbiosgrubパーティションを作成する。

(parted) mkpart _ 1mib 2mib
(parted) toggle 1 bios_grub

partedのhelpコマンドによるとmkpartコマンドの第一引数はprimaryとかextendedを指定しろと書いてあるのだが、これはおそらくDOSパーティション用で、GPTの場合第一引数は単なる名前になるようだ。この名前がどのように使われるかは私は知らない。この記事では名前は全部 _ で済ますことにする。

次にboot, swap, root用の各パーティションを作成する。

(parted) mkpart _ 2mib 1gib
(parted) mkpart _ 1gib 3gib
(parted) mkpart _ 32gib 48gib

DOSパーティションと違い、パーティションのタイプを指定する必要はない。また、3gib と 32gib の間の「穴」は、後々簡単に swap パーティションを拡大できるようにするための余地である。

(最後のパーティションをディスクいっぱいまで使いたい場合はmkpart _ 32gib -0gibとすればよい; ただし同期に長大な時間がかかる)

ここまでの作業でパーティションは以下のようになる。

(parted) unit mib
(parted) print free
Number  Start     End         Size         File system  Name  Flags
        0.02MiB   1.00MiB     0.98MiB      Free Space
 1      1.00MiB   2.00MiB     1.00MiB                   _     bios_grub
 2      2.00MiB   1024MiB     1022MiB                   _
 3      1024MiB   3072MiB     2048MiB                   _
        3072MiB   32768MiB    29696MiB     Free Space
 4      32768MiB  49152MiB    16384MiB                  _
        49152MiB  1907729MiB  11858577MiB  Free Space

確認してリブートする。

(parted) quit
$ sudo reboot

インストール

Ubuntuデスクトップインストーラで起動しインストールを開始する。[ディスク領域の割り当て] の場面では [それ以外] を選んで、手動で ext4 ファイルシステムや swap を設定し、マウントポイントも設定する。

(つづく)

Linux (Ubuntu 11.04)で2TB超のHDをソフトウェアRAID化する (1)

今回入手したHP Z800には500GBのHDが付いていてWindows 7 Professionalがインストールされているが、Windowsは必要ないのでLinux (Ubuntu)に入れ替える。最終的な目標は外付けの集合型HD箱にHDを5台詰め込んでRAID 5で運用することだが、本体に内蔵するシステム用HDもRAIDで運用したいと考えた。

LinuxでソフトウェアRAID (RAID 1)を構成する話なんてありふれていて、ちょろっと検索して調べれば簡単に済む話だと思っていたが、これが大違い。検索の結果、一番簡単なやり方はインストーラで最初からRAID構成にすること、ということだったので試してみたところ、

  • Ubuntu デスクトップインストーラではRAID構成はできない。
  • Ubuntu Alternative インストーラならできるらしいが、HP Z800のハードウェア(おそらくイーサネットチップ)がサポートされておらずインストーラがうまく動かない。
  • それ以前の話として、2TBを超えるHDのパーティション切りにインストーラが対応できていない。

などの理由で一筋縄ではいかないということが判明した。それからしばらくの間格闘した結果、うまく設定できる方法がわかったのでここに記述する。

材料

  • HP Z800(付いてきた500GBのHDは外す)
  • 2TB HD × 2(512バイト/セクタ)(sda, sdbと呼ぶ)
  • Ubuntu 11.04インストールDVD(デスクトップ版)

ゴールの設定と作業の概要

ゴール: boot, swap, rootの各ファイルシステム用のパーティションをRAID 1で運用する。

作業の概要は以下のようになる。

  1. sdaをパーティション分けする。
  2. sdaに Ubuntu 11.04 デスクトップ版をインストールする。
  3. sdbにRAID 1を構成する。このとき相方が無いsdb 1台のみの設定で構成する。
  4. sdbにsdaの内容をコピーし、相方の無いsdbのみのRAID 1で起動できるようにする。
  5. (この時点でsdaは全く使われていない状態になっている)sdaをsdbのみで運用されているRAID 1に参加させる。

(つづく)

HP Z800 Workstateion購入

家にあるLinuxサーバの老朽化が気になっていたのだが、2011年7月に開催されたnVIDIAのワークショップに参加したところHPがTesla C2050入りのワークステーションを台数限定で特売するという情報を得たので、よい機会だと思い購入してサーバのリプレースをすることになった。

スペックは以下の通り。

  • 筐体: HP Z800
  • CPU: Intel Xeon E5620 (2.4GHz, 4コア) × 2 水冷
  • RAM: 16GB
  • VGA: nVidia Tesla C2050 × 2

HP Z800

非常に重くて水冷にもかかわらずかなりうるさいが、幅と高さがそれほど無く(奥行きはある)内部のアクセスも非常に簡単な優秀な筐体だ。今購入すると100万円近くになる構成だが、なんと半分くらいの値段で買うことができた。それでも高いが前の奴は8年も前に買ったものだからまあいいとしよう。

元々内蔵されているHDにはWindows 7 Professionalがプリインストールされているが、これは外してそのまま保管し、最近安くなった2TのHDを2台入れてLinuxでソフトウェアRAIDを設定することにした。あちこちに参考になる記事があるし、簡単にできると思っていたのだが意外にもかなりはまったので次回はこれについて書く予定。

References

HP Z800 Workstationのメーカーページ: [日本HP Z800 Workstation]

Intel Xeonは種類がたくさんあってどう違うのかよくわからなかったので以下を参考にした: [インテル® Xeon® プロセッサー 5600 番台]

2TのHDは日立HGST製のをAmazonで買った: [Amazon.co.jp: 日立 HGST Deskstar パッケージ版 3.5inch CoolSpin 2.0TB 32MB SATA 6.0Gbps 0S03224: パソコン・周辺機器]。後に増設する外付けのRAID 5箱用と(あとスペアと)合わせて8箱購入。