2009年3月30日月曜日

池袋出張

物理学会に行ってきました。
場所は立教大学。池袋です。すんげーレトロで美しい建物の大学でよかったです。そして立地良すぎ。池袋、個人的には気に入ったかも。でかいデパート、ジュンク堂、ハンズとかでなんでもそろうし全く不便ない。Echikaの甘物などウマーなものもあるしなぁ。ビール半額につられて行ったのに、夢の庭なる居酒屋が料理おいしかった。から揚げが予想外にうまくてびっくりした。その前に東京在住の友人が連れて行ってくれた「音音」なるところもご飯おいしかったので、池袋の印象はイイ。

今回は、はりこんでいつもより高い目のホテルに泊まった。なんか元々不眠気味で、物音が気になると眠れない。ちょっと安い目だと廊下の音声が猛烈に聞こえたり、隣の鼾が聞こえたりで安眠できない。これまでは出張で足でるとかあほらしいてやってられへんとギリッギリのところに泊ってた、そしてそのたびに疲労困憊。健康は金に代え難いと最近思うようになってきたので快適さ重視で選んだ。ストリックス東京というとこにした。コンフォートシングルにしたら広くて快適だった。ベット寝心地いいし、クーラーから変な音するのとか言ったらちゃんとチェックしてくれたし加湿器貸してくれるし、朝ごはんバイキングじゃなしに各人に出してくれるし、ネットの調子がちと悪かった以外文句なし。快適に過ごしたんでかなりまじめに学会出た。快適さはモチベーションに影響するな。

学会も今回は自分の研究にかなりリンクするのが多くて業界の流行とか探れてよかった。レビューセッションで近藤効果の話もあったので聞きに行く。教科書とかだと書いてない、歴史というか流れみたいなものをちょっと窺い知れてよかったかも。大抵の教科書はS-d模型とAnderson模型の話を全く別物のようにぶったぎって書いていて、初見だとものすごく混乱する。S-d模型のほうは、スピンありきの領域だけが有効であるとしている。その結果、Anderson模型の部分空間での有効ハミルトニアンとなっている。そのせいで、摂動展開では局在スピン領域と近藤芳田一重項領域がつながらない。Anderson模型の数値繰り込み群の論文に書いてある謎の図の見方が初めてわかったわ。模型をシンプルにしたせいでシンプルな手法では解けなくなったとかその辺が教訓的であると思う。

2009年3月20日金曜日

sakuraエディタでTeX

こないだ、後輩にTeXの使い方を教える機会があって、フリーでいかにTeX環境を構築するかちゅうのをいろいろ考えた。

TeX+GS+GSViewとか本体
http://www.ms.u-tokyo.ac.jp/~abenori/mycreate/index.html
からインストーラーを頂いて、楽にインストールさせてもらう。

エディタ
sakuraでキーワード補完、色分け
マクロでplatex実行→dviout表示

がフリーでは一番楽なんじゃないかと思った。Winshellはなんか個人的に使いにくい…
そんなわけでplatex実行用のマクロを探す。
http://doter.seesaa.net/article/38297286.htmlからもらってきたものの、自分とこの環境ではMyDocumentとかにおいてあるTexファイルをコンパイルしようとするとエラーが出る。原因は、Document and Settingの空白っぽい。これだからWindowsでTexは…。というわけで、C直下に標準でインストールされるtexフォルダに一時的にコピーして、コンパイルするように変更する。
こんな感じ。あらかじめC:\tex\tempを作っとかないとエラーでる。終わった後にコピーしたtemp内のは消す仕様。JavaScript


var objShell = new ActiveXObject("WScript.Shell");
var myObject = new ActiveXObject("Scripting.FileSystemObject");
var i;
var pathlength;
var FileName; //原型ファイル名格納用
var TeXFileName; //TeXファイル名格納用
var DviFileName; //DVIファイル名格納用
var PathName ; //path名格納
var FileName2; //コピー先の名前を格納
Editor.FileSave(); //ファイル上書き保存
FileName=Editor.GetFileName(); //ファイルパスの取得

TeXFileName=""; //初期化
DviFileName=""; //初期化
PathName="";
FileName2="";


for(i=0;i<FileName.length;i++){
if(FileName.charAt(i)=="\\"){ //ファイルパスの「\」を「/」に変換
TeXFileName=TeXFileName+"/";
}else{
TeXFileName=TeXFileName+FileName.charAt(i);
}
if(i<FileName.length-3){ //拡張子をdviに変換
DviFileName=DviFileName+TeXFileName.charAt(i);
}else{
if(i==FileName.length-3)DviFileName=DviFileName+"d";
if(i==FileName.length-2)DviFileName=DviFileName+"v";
if(i==FileName.length-1)DviFileName=DviFileName+"i";
}
}

for(i=0;i<FileName.length;i++){
if (FileName.charAt(i)=="\\"){
pathlength=i+1;
}
}

for (i=0; i<pathlength;i++){
PathName=PathName+TeXFileName.charAt(i);
}

for (i=0;i<FileName.length-pathlength;i++){
FileName2=FileName2+TeXFileName.charAt(i+pathlength);

}
//objShell.Popup('FileNameは"' + FileName2 + '"です', 0, "ファイル名", 0); //debug用
myObject.CopyFile(TeXFileName, "C:/tex/temp/"+FileName2); //tempフォルダをあらかじめ作っておくこと
objShell.Run("C:/tex/bin/platex "+"C:/tex/temp/"+FileName2,1,1); //TeXコンパイラ実行(各自でパス変更)
objShell.Run("C:/tex/dviout/dviout.exe -1 "+DviFileName,1,0); //DVIビューアの実行(各自でパス変更)
myObject.DeleteFile("C:/tex/temp/"+FileName2);

2009年3月13日金曜日

CUDA+Fortran

昨日から今日にかけてホワイトデーのお返しで菓子をあちこちからいっぱいもらったのでなんか嬉しい。もともと甘いもんスキーなので。先生方からもお返しもらってしまった。若干恐縮するなぁ。
研究室の工事があって、夕方から猛烈に接着剤のにおいがしだして、頭痛+アレルギー症状が劇化したので早々に帰ってきた。昔から溶剤なにおいとか防虫剤なにおいとか芳香剤なにおいが嫌いというか嗅ぐと気分悪くなったり頭痛くなる。なわけで今日はあんまり仕事してない。まぁ実は数値計算の新バージョンの計算コードの動作チェック(発狂しそうにめんどくさかった)も完了してあとはひたすら計算機のパワーに任せるだけの段階になったので気分的にのんびりしてたりする。

そんなわけで昨日に引き続きCUDAで遊ぶ。
計算物理のぎょーかいでは速度命だったり昔々の偉人がつくったコードを使いまわしたり、線形代数の神ライブラリLapackを使うことが多いのでいまだにFortranが幅を利かせている。他の分野ではFortranなにそれオイシイの?だろうけどなぁ…。自分もメインはFortran90でありこれまで作ってきたのも大半がそれベース。なのでその一部をCUDAで高速化しようと思うと、FortranからCUDAコードを呼び出す方法をお勉強しとかなあかん。
FortranとCはわりかし互換性がよくて、もともと相互にFortran中でCの関数を呼ぶとかC中でFortranのサブルーチンを呼び出すとかができる。CUDAはCがベースなので、Fortranから呼び出すことも実は比較的容易っぽい。

CUDAに限らず、FortranとCを混在させるときの注意点
・FortranからCの関数を呼ぶときには、呼び出される側のCの関数にexternを付けておく、最後に_を付けておく。
・Fortranはそもそもサブルーチン等の引数が参照渡しなのでC側では引数をポインタとして扱わないといけない。
・Fortranは配列が1から始まる、Cでは0から始まる。Fortranでは列優先なので(a,b)の次は(a+1,b)、Cでは行優先なので(a,b)の次は(a,b+1)。

とりあえず昨日の配列の和のコードをベースに作る
Fortranで配列を準備→CUDA側に引数で渡す、GPUで計算→Fortranサイドで出力チェックてなことをやってみようと。環境はLinux(CentOS5)+ifort

CUDA側(testf.cu)



#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>


__global__ void wa ( int *array1, int *array2, int len)
{
int i;
for (i=0; i<len ;i++)
array1[i]= array1[i]+array2[i];
return;
}

extern "C" void cudafunc_ (int* arrayH1, int* arrayH2, int* Np)
{
int i;
int N;
int* arrayD1;
int* arrayD2;

size_t array_size;

N=*Np;

printf("inside the C code \n");
printf("input array \n");

printf("input of H1 \n");
for (i=0;i<N;i++)
printf("%d\n",arrayH1[i]);

printf("input of H2\n");
for (i=0;i<N;i++)
printf("%d\n",arrayH2[i]);


array_size = sizeof(int) * N;

cudaMalloc( (void **) &arrayD1, array_size);
cudaMalloc((void **) &arrayD2, array_size);

cudaMemcpy(arrayD1,arrayH1,array_size,cudaMemcpyHostToDevice);
cudaMemcpy(arrayD2,arrayH2,array_size,cudaMemcpyHostToDevice);

wa <<<dim3(1,1),dim3(1,1,1)>>>(arrayD1,arrayD2,N);

cudaMemcpy(arrayH1,arrayD1,array_size,cudaMemcpyDeviceToHost);

printf("output\n");
for (i=0;i<N;i++)
printf("%d\n",arrayH1[i]);


return ;

}




Fortran側(testcuda.f90)



program main
!test for CUDA+Fortran

!the length of array
integer,parameter :: N=8
integer :: arrayH1(1:N)
integer :: arrayH2(1:N)
integer :: i


!setting the input array
do i=1,N
arrayH1(i)=i
arrayH2(i)=i*2
end do

call cudafunc(arrayH1,arrayH2,N)

print*,"output in fortran code"

do i=1,N
print*,arrayH1(i)
end do

end program main


Makefileの例

all: CUDAfortran

# Define Fortran compiler
FC= ifort

CUDAfortran: testcuda.f90 testf.o
$(FC) -o CUDAfortran testcuda.f90 testf.o -L/usr/local/cuda/lib -lcudart

testf.o: testf.cu
nvcc -c testf.cu

clean:
rm testf.o CUDAfortran


うむ、なんとか動いた。これであれやこれやをGPUで計算できるわけだがなんと10秒ルールとやらがあるらしい。GPU上のジョブの時間制限10秒ってマジっすか?10秒で計算終わってもデータ転送に時間かかってるっぽいしなんだか用途の制限多いんじゃ…?まぁ面白そうではあるので引き続きいろいろ調べると思う。

2009年3月12日木曜日

CUDAその3

研究室にNIVIDA Tesla C1060が入ったやつが導入されたのでぼちぼちCUDAをいじってみる。

TeslaはGPUのくせに、ビデオ出力の機能がない。ひたすら数値演算に特化している。とりあえず、C1060だとマルチプロセッサが240あってしかも各プロセッサに8つのコアが含まれているらしい。超並列処理とかいっちゃってるわけだ。
GPGPUのウリはこの並列化らしい。各プロセッサの8つのコアはSIMT(single instruction multi thread)という形式で同じ内容の手続きを複数のスレッドに分けて実行する(SIMDと似ているがこっちのほうがややこしい処理を並列化できるんか)。スレッドは8*4=32が基本単位になっていて、32スレッドを1ワープと数えるらしい。変なの。

母体となるコードはCPU上で実行される。コードのなかでも並列化が肝になってくるところをGPU上で行うのが普通。GPU側で処理される手続きをカーネルと呼ぶ。
ふつーカーネルで行われる手続きは並列化される。並列化の基本単位はスレッドなんだが、CUDAではスレッドの塊とさらにその塊の集まったモノを定義する。スレッドの塊はスレッドブロック、スレッドブロックの集まりをグリッドという。ひとつのカーネルに対して、ひとつのグリッドが割り当てられる。スレッドブロックのインデックスは2次元まで、スレッドそのもののインデックスは3次元までとることができる。こんなに入れ子な仕組みにするのはたぶんGPUのハード側の特性(マルチプロセッサが並列+そのなかのコアが並列)になってるからだろう。それがメモリの階層性にも反映されている。メモリはグローバルメモリとシェアードメモリの2つに大別される。グローバルメモリはグリッド内すべてで共有であり、シェアードメモリはブロック内のみで共有される。シェアードメモリのほうが圧倒的にアクセスが早い。

CUDAのプログラムの大まかな流れは

CPUサイドでデータ処理

GPU上でメモリ確保(cudaMalloc)

GPUへデータ転送 (cudaMemorycpy)

GPUで計算(aaa<<>>(x,y,z))

GPUからデータ転送(cudaMemorycpy)

こんな感じ。めっちゃ簡単な一次元の配列を足し算するだけのをつくってみた。バージョンはCUDA v2.0。2.0になってちょこちょこ変更があったらしく、Web上の旧バージョンのサンプルとはヘッダファイルの名前が変わってたりというトラップあり。要注意。


#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>

#define N (32)

__global__ void wa ( int *array1, int *array2, int len)
{
int i;
for (i=0; i<len ;i++)
array1[i]= array1[i]+array2[i];
return;
}

int main (int argc,char *argv[])
{
int i;
int arrayH1[N];
int arrayH2[N];
int arrayoutput[N];

int* arrayD1;
int* arrayD2;

size_t array_size;
printf("input array \n");
for (i=0; i<N;i++) arrayH1[i]=i;
for (i=0; i<N;i++) arrayH2[i]=i*2;

printf("input of H1 \n");
for (i=0;i<N;i++)

printf("%d\n",arrayH1[i]);

printf("input of H2\n");
for (i=0;i<N;i++)

printf("%d\n",arrayH2[i]);


array_size = sizeof(int) * N;

cudaMalloc( (void **) &arrayD1, array_size);
cudaMalloc((void **) &arrayD2, array_size);

cudaMemcpy(arrayD1,arrayH1,array_size,cudaMemcpyHostToDevice);
cudaMemcpy(arrayD2,arrayH2,array_size,cudaMemcpyHostToDevice);
wa <<<dim3(1,1),dim3(1,1,1)>>>(arrayD1,arrayD2,N);

cudaMemcpy(arrayoutput,arrayD1,array_size,cudaMemcpyDeviceToHost);

printf("output\n");
for (i=0;i<N;i++)

printf("%d\n",arrayoutput[i]);


return 0;

}



なんか(void**)が??だったけど、CUDAではこういう型もあるっぽい。void*はvoid型ポインタだからその拡張か?C言語自体あんまりしらんのでなかなか目新しいのが満載だ。今回つかったのは単純のためまったく並列化もなんもせんと1ブロック1スレッド。さて次は並列化を学習しよう。

面談

気がつけば3月も中旬になりつつある。早い。
ここんとこなんだか忙しかった。毎回忙しいって言ってるな。ワークショップの手伝いがあったり、面談うけたり、論文の再投稿したり、OPローズダスト読み出したりしてたからだ。OPローズダストは亡国のイージスと同じ著者。文庫本で上中下なのでなかなか時間かかっている。ここんとこ夜更かししてしまう原因。

今週は月曜に、他の学科の先生に研究内容を説明して評価をうけるっていうなかなか重い仕事があったので、一週間が長く感じる。なんでそんなお仕事があったかというとGCOE関連。うちの研究室がかんでいるGCOEでは学生を研究者に養成するのに力点が置かれているらしく、プロジェクトは学生主体でチームリーダーも学生。一応数少ない日本人Dの一人なので必然的にチームリーダーとやらになってた。まぁとりたてなにもしていないんだけど(予算はおいしく使わせてもらいました)。養成事業の一環?として、外部評価を受けるというのがあるんだなー。ワークショップに駆り出されたついでに、そこに参加している研究室の教授の方にお願いして、面談してもらった。前々から知っている先生とはいえやっぱその道のプロに説明して評価されるっちゅうのは緊張する。どこがいい点なのか、今度どういう方向にすればいいかとかいろいろコメントもらえたのでよかった。なかなか学生にしてみればしんどいタスクだけどこの試みっていいんじゃないのかなぁと。自分の研究てのは意外なほど自分ではウリが分からない。外部の先生に見てもらって、どこが興味深いと思ってもらえるのかとか、業界のトレンドにどう絡めていけばいいのかとかをコメントしてもらえるのはすごくいいことだと思う。他の研究室の先生に「研究内容を聞いてください!」なんて、こんな大義名分がなきゃ言いづらいしな。研究はそりゃ自分がやってて楽しいのが何よりだけど、ひとから興味持ってもらってナンボなとこある。他人が興味持ってくれる切り口がどこかを知るのは強みになるだろう。来年度は学振あるのでリーダーはできない、補佐にまわることになる。さて誰を後釜にするんだ、勧誘せんと。

まぁそんなわけで今後の方向なんぞも模索しつつある今日この頃。GPGPUも導入されたことだしいろいろやること多いわ。

2009年3月1日日曜日

道具

気がつけば三月。2月はかなり忙しかったので、なんか本当にあっというまだった。

私のどーでもいい持論の一つは、「人のやる気は道具の性能に大きく左右される」ってやつだ。PCとかソフトウェアの起動が遅いとその時点でなんかやる気失せるし、入力補完ないエディタとか打つのめんどくさくなってくる。とまぁやる気のないのを環境のせいにしてみてるわけだが。
研究はともかく、日常生活でどうもやる気が起きないことの一つが掃除だったりする。さすがに最低限掃除機かけたりはしているので、汚宅とかゴミ屋敷レベルには達してはいないが、なんとはなしに埃が多い。掃除機をエルゴラピードにしてコードレスにしてから前より頻繁に掃除機つかってる割には埃レヴェルが低下しない。絨毯が敷いてあるのが主な原因と思われる。これが掃除機の限界というものかとか勝手に納得して、埃じゃ死なんと達観してた。
が、こないだ、電球が切れたのでコーナンに行ったら、粘着テープをコロコロころがすタイプのブツが目に入ったので、買って試してみた。埃めっちゃとれるやんか…。もしかして、みんな掃除機とこれの合わせ技をつかってたのか?というかそれが常識だったのか…?家事全般の方法がよくわからん上に常識がないのでコロコロが進化しているとは知らなかった。フローリング、畳、タイル、カーペット全部これ一個でOKタイプ、しかも持ち手が伸びるタイプまである。ニトムズとかいうメーカーのは、切れ目やら粘着剤が溝上についているとか、ワンタッチでケースが開くとかなかなか工学的にイイ感じ満載だ。うーん持ってコロコロしてるだけでなんとかなるなら、掃除してやろうではないかという気にもなるってもんだ。やっぱりやる気を改善するにはいい道具を見つけることだな。
で、休みの日に仕事に飽きた合間に最近ちょくちょくコロコロしてたら、なんか家にいる時の花粉症の症状がすごくマシである。花粉症対策の一歩はまず掃除からってな文章を見るたびに掃除苦手なもんで、「けっ、原因はヒスタミンの分泌っしょ」とか思ってたけど、本当だったんだな。3月中はマメにコロコロ転がすことにしよう。