■
Fortranでバイナリデータを書いて、CとPython(numpy)で読む
Ubuntu-14.04 64bit上のgcc-4.8.4でテスト。
test.F90
program test implicit none integer :: i, j, count real(kind=8) :: data(4, 3) print '("Number of bits used for data:", i5)', storage_size(data) count = 1 do i = 1, 4 do j = 1, 3 data(i, j) = count write(*, '(F15.8)', advance='no') data(i, j) count = count + 1 end do print *, '' end do open(unit=11, file="data.bin", status="REPLACE", access="STREAM") write(11) data close(unit=11) end program test
% gfortran test.F90 % ./a.out Number of bits used for data: 64 1.00000000 2.00000000 3.00000000 4.00000000 5.00000000 6.00000000 7.00000000 8.00000000 9.00000000 10.00000000 11.00000000 12.00000000
test.c
#include<stdio.h> int main(void) { FILE *fp; int i, j; double x; printf("Number of bits used for data: %d\n", (int)(sizeof(double) * 8)); fp = fopen("data.bin", "rb"); if (!fp) { printf("File open failed.\n"); return 1; } for (j = 0; j < 3; j++) { for (i = 0; i < 4; i++) { fread(&x, sizeof(double), 1, fp); printf("%f ", x); } printf("\n"); } return 0; }
% gcc test.c % ./a.out Number of bits used for data: 64 1.000000 4.000000 7.000000 10.000000 2.000000 5.000000 8.000000 11.000000 3.000000 6.000000 9.000000 12.000000
test.py
#!/usr/bin/python import numpy as np shape = (3, 4) dt = np.dtype(('double', shape)) print("Number data type is %s." % dt) data = np.fromfile("data.bin", dtype=dt)[0] print(data)
% ./test.py Number data type is ('<f8', (3, 4)). [[ 1. 4. 7. 10.] [ 2. 5. 8. 11.] [ 3. 6. 9. 12.]]
■
c.p.
Cyclic permutation?
■
Fortranはじめました
Fortranでプログラムを書くことになった。
まず他人が書いたコードを読み、修正するところがスタートである。
Fortranは古い書き方を許せば書き方に自由度がありすぎるようだ。
なんとなくは読めるけど、細かいところで言語仕様がわからずつまずく。
そのときネットで情報を探すがなかなかみつからない。
どういう書き方が「今」推奨されているのかという情報がなかなか見つからない。
とりあえず、なんとか見つかった情報をコピペしておく。
Fortran Best Practices — Fortran90 1.0 documentation
Fortran Wiki
Fortranで書いてPythonで読むための情報
scipy.io.FortranFile — SciPy v0.19.0.dev0+812be1e Reference Guide
numpy.fromfile — NumPy v1.11 Manual
Cookbook/FortranIO - SciPy wiki dump
Reading a direct access fortran unformatted file in Python - Stack Overflow
https://software.intel.com/en-us/node/579701
C H A P T E R 2 - Fortran Input/Output
Stream Input Output in Fortran Wiki
■
ビール Pale pig
めちゃうまい。
■
VASP-GPU (Tesla K80)
Ubuntu 14.04の場合、CUDAのインストールは簡単。
Installing CUDA Toolkit 7.5 on Ubuntu 14.04 Linux | R Tutorial
仕事で使っているGPUマシンにはTesla K80が一枚(2GPU)と、GeForce GT 610が一枚刺さっている。
GeForceの方もCUDAから見えてしまうのでTesla K80だけがGPU計算で見えるようにしたい。そのための環境変数がある。
export CUDA_VISIBLE_DEVICES="0,2"
ただ、どのカードがどのIDを持っているのかがわからないので困った。試行錯誤で決定した。
sampleのdeviceQueryをmakeして、CUDA_VISIBLE_DEVICESと共にどのGPUが見えているかチェックするのが良いだろう。
GPU-UUIDを使うというのが正解らしい(
https://docs.nvidia.com/deploy/pdf/CUDA_Multi_Process_Service_Overview.pdf)
nvidia-smi -q
でGPU-UUIDが確認できる。
次に、CUDA-aware Open MPIを作る。--with-cuda付でコンパイルすれば良い。
それを使ってVASP-GPUもコンパイルした。
VASP-GPUのウエブサイトはここ。GPU port of VASP - Vaspwiki
パフォーマンステストは次の設定で行った。
POSCAR
S Cu Ga 1.0 10.5481205800000009 0.0000000000000000 0.0000000000000000 0.0000000000000000 10.5481205800000009 0.0000000000000000 0.0000000000000000 0.0000000000000000 10.4684162900000004 S Cu Ga 32 16 16 Direct 0.3739084011856084 0.3750000000000000 0.6250000000000000 0.8729603650000000 0.3750000000000000 0.6250000000000000 0.3729603650000000 0.8750000000000000 0.6250000000000000 0.8729603650000000 0.8750000000000000 0.6250000000000000 0.1250000000000000 0.3729603650000000 0.3750000000000000 0.6250000000000001 0.3729603650000000 0.3750000000000000 0.1250000000000000 0.8729603650000000 0.3750000000000000 0.6250000000000001 0.8729603650000000 0.3750000000000000 0.1270396350000000 0.1250000000000000 0.6250000000000000 0.6270396350000000 0.1250000000000000 0.6250000000000000 0.1270396350000000 0.6250000000000001 0.6250000000000000 0.6270396350000000 0.6250000000000001 0.6250000000000000 0.3750000000000000 0.1270396350000000 0.3750000000000000 0.8750000000000000 0.1270396350000000 0.3750000000000000 0.3750000000000000 0.6270396350000000 0.3750000000000000 0.8750000000000000 0.6270396350000000 0.3750000000000000 0.1229603650000000 0.1250000000000000 0.1250000000000000 0.6229603650000000 0.1250000000000000 0.1250000000000000 0.1229603650000000 0.6250000000000001 0.1250000000000000 0.6229603650000000 0.6250000000000001 0.1250000000000000 0.3750000000000000 0.1229603650000000 0.8750000000000001 0.8750000000000000 0.1229603650000000 0.8750000000000001 0.3750000000000000 0.6229603650000000 0.8750000000000001 0.8750000000000000 0.6229603650000000 0.8750000000000001 0.3770396350000000 0.3750000000000000 0.1250000000000000 0.8770396350000003 0.3750000000000000 0.1250000000000000 0.3770396350000000 0.8750000000000000 0.1250000000000000 0.8770396350000003 0.8750000000000000 0.1250000000000000 0.1250000000000000 0.3770396350000000 0.8750000000000001 0.6250000000000001 0.3770396350000000 0.8750000000000001 0.1250000000000000 0.8770396350000003 0.8750000000000001 0.6250000000000001 0.8770396350000003 0.8750000000000001 0.2500000000000000 0.2500000000000000 0.5000000000000000 0.7500000000000000 0.2500000000000000 0.5000000000000000 0.2500000000000000 0.7500000000000000 0.5000000000000000 0.7500000000000000 0.7500000000000000 0.5000000000000000 0.0000000000000000 0.2500000000000000 0.2500000000000000 0.5000000000000000 0.2500000000000000 0.2500000000000000 0.0000000000000000 0.7500000000000000 0.2500000000000000 0.5000000000000000 0.7500000000000000 0.2500000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
INCAR
PREC = Accurate GGA = PS IBRION = -1 NELMIN = 5 ENCUT = 479.242400 EDIFF = 1.000000e-08 ISMEAR = 0 SIGMA = 1.000000e-02 IALGO = 38 LREAL = .TRUE. ADDGRID = .TRUE. LWAVE = .FALSE. LCHARG = .FALSE.
KPOINTS
Automatic mesh 0 Gamma 2 2 2 0.000 0.000 0.000
PAW datasetはS,Cu_pv,Ga_d (PBE).
結果は次の通り。
CPUがXeon E5-2643 v3 @ 3.40GHzの場合
12コアCPUのみでおよそ1800秒。
2コア2GPUでおよそ750秒。
4コア2GPUでおよそ700秒。
6コア2GPUでおよそ680秒。
8コア2GPUでおよそ1100秒。
12コア2GPUでおよそ1050秒。
4コア2GPU(MPS)でおよそ640秒。
6コア2GPU(MPS)でおよそ580秒。
4コア1GPUでおよそ1190秒。
CPUがXeon E5-2603 v3 @ 1.60GHzの場合
12コアCPUのみでおよそ3300秒。ほぼクロック通り。
2コア2GPUでおよそ920秒。CPUの能力も無視できない。
4コア2GPUでおよそ890秒。
6コア2GPUでおよそ820秒。
8コア2GPUでおよそ1500秒。
12コア2GPUでおよそ1410秒。
4コア2GPU(MPS)でおよそ830秒。
6コア2GPU(MPS)でおよそ820秒。MPSの効果はあまりなし。
4コア1GPUでおよそ1360秒。CPU差はだいぶ縮まる。
Tesla K80カードが2枚のマシンで4 GPUを使うと半分程度のパフォーマンスしか出せなかった。
Tesla K80カード2枚の計算機で同時に同じ計算を二つ実行するとそれぞれ、4コア2GPUでおよそ1080秒。
NSCのPeter Larssonのブログ(Running VASP on Nvidia GPUs - Peter Larsson
)では、
CUDA Multi Process Service (MPS)を使うべしと書いてある。
export CUDA_VISIBLE_DEVICES="0,2" mkdir /tmp/nvidia-mps export CUDA_MPS_PIPE_DIRECTORY=/tmp/nvidia-mps mkdir /tmp/nvidia-log export CUDA_MPS_LOG_DIRECTORY=/tmp/nvidia-log nvidia-cuda-mps-control -d
clientsがserverに接続できたかは、ログを見ればわかる。
https://devtalk.nvidia.com/default/topic/887822/fail-to-launch-cuda-mps/
Larssonの書いているように、もっと原子数が多い系でGPUがより効果的であると思うが、
Gamma-onlyバージョンはまだサポートされていないので、100から200原子くらいの対称性の低い系がスイートポイントかなあ。