2017年6月13日火曜日

ViennaCLのBenchmark BLAS on iMac 21.5 Late 2013

  機種名: iMac
  機種 ID: iMac14,3
  プロセッサ名: Intel Core i5
  プロセッサ速度: 2.9 GHz
  プロセッサの個数: 1
  コアの総数: 4
  二次キャッシュ(コア単位): 256 KB
  三次キャッシュ: 6 MB

  メモリ: 16 GB

  チップセットのモデル: NVIDIA GeForce GT 750M
  種類: GPU
  バス: PCIe
  PCIe レーン幅: x16
  VRAM(総量): 1024 MB
  製造元: NVIDIA (0x10de)

この環境で、ViennaCLのベンチマークを走らせてみる。

まず、CPUから。
./examples/benchmarks/dense_blas-bench-cpu 
Benchmark : BLAS
----------------
sCOPY : 3.07 GB/s
sAXPY : 3.74 GB/s
sDOT : 3.02 GB/s
sGEMV-N : 0.431 GB/s
sGEMV-T : 0.767 GB/s
sGEMM-NN : 0.591 GFLOPs/s
sGEMM-NT : 0.541 GFLOPs/s
sGEMM-TN : 0.574 GFLOPs/s
sGEMM-TT : 0.543 GFLOPs/s
----
dCOPY : 5.83 GB/s
dAXPY : 7.02 GB/s
dDOT : 5.7 GB/s
dGEMV-N : 0.82 GB/s
dGEMV-T : 1.46 GB/s
dGEMM-NN : 0.557 GFLOPs/s
dGEMM-NT : 0.51 GFLOPs/s
dGEMM-TN : 0.579 GFLOPs/s
dGEMM-TT : 0.573 GFLOPs/s
OpenMP版
Benchmark : BLAS
----------------
sCOPY : 9.14 GB/s
sAXPY : 10.3 GB/s
sDOT : 9.33 GB/s
sGEMV-N : 1.28 GB/s
sGEMV-T : 2.34 GB/s
sGEMM-NN : 2.01 GFLOPs/s
sGEMM-NT : 1.97 GFLOPs/s
sGEMM-TN : 2.04 GFLOPs/s
sGEMM-TT : 1.97 GFLOPs/s
----
dCOPY : 12.7 GB/s
dAXPY : 18.1 GB/s
dDOT : 15.4 GB/s
dGEMV-N : 2.15 GB/s
dGEMV-T : 3.75 GB/s
dGEMM-NN : 2.02 GFLOPs/s
dGEMM-NT : 1.99 GFLOPs/s
dGEMM-TN : 2.06 GFLOPs/s
dGEMM-TT : 2.07 GFLOPs/s
コア分だけ速くなってる。
次はOpenCL
./examples/benchmarks/dense_blas-bench-opencl 

----------------------------------------------
               Device Info
----------------------------------------------

Name:                GeForce GT 750M
Vendor:              NVIDIA
Type:                GPU 
Available:           1
Max Compute Units:   2
Max Work Group Size: 1024
Global Mem Size:     1073741824
Local Mem Size:      49152
Local Mem Type:      1
Host Unified Memory: 0


Benchmark : BLAS
----------------
sCOPY : 19.3 GB/s
sAXPY : 46.8 GB/s
sDOT : 41.6 GB/s
sGEMV-N : 25.5 GB/s
sGEMV-T : 23.7 GB/s
sGEMM-NN : 31.6 GFLOPs/s
sGEMM-NT : 33.9 GFLOPs/s
sGEMM-TN : 29.5 GFLOPs/s
sGEMM-TT : 31 GFLOPs/s
----
dCOPY : 48.4 GB/s
dAXPY : 55.2 GB/s
dDOT : 44.9 GB/s
dGEMV-N : 23.5 GB/s
dGEMV-T : 23.2 GB/s
dGEMM-NN : 14.8 GFLOPs/s
dGEMM-NT : 14.9 GFLOPs/s
dGEMM-TN : 14.2 GFLOPs/s
dGEMM-TT : 14.6 GFLOPs/s

そして、CUDA。
./examples/benchmarks/dense_blas-bench-cuda
Benchmark : BLAS
----------------
sCOPY : 24.5 GB/s
sAXPY : 52.1 GB/s
sDOT : 37.5 GB/s
sGEMV-N : 40.8 GB/s
sGEMV-T : 26.4 GB/s
sGEMM-NN : 38.2 GFLOPs/s
sGEMM-NT : 38 GFLOPs/s
sGEMM-TN : 39.6 GFLOPs/s
sGEMM-TT : 38.1 GFLOPs/s
----
dCOPY : 56.3 GB/s
dAXPY : 52.8 GB/s
dDOT : 47.1 GB/s
dGEMV-N : 37.4 GB/s
dGEMV-T : 27.1 GB/s
dGEMM-NN : 22.5 GFLOPs/s
dGEMM-NT : 23 GFLOPs/s
dGEMM-TN : 22.5 GFLOPs/s
dGEMM-TT : 22.4 GFLOPs/s

GPUの圧勝。ただ、CPU版の単精度計算と倍精度計算でFLOPS値が同じくらいなのは、AVX2の命令系を使っていないのだろう。まあ、使っても単精度が倍になるくらいか。それともSIMDは使ってないのか。それならば最大16倍速くなる。

2017年6月11日日曜日

Joomla 2.5 -> 3.5 ERRO: Could not open /var/www/bin/index.html for writing.

やっと終わった。
CentOS6.8では、PHP5.1がデフォルトで入っていて、remiリポジトリから5.6をとってきてインストールすることは出来た。これは別記事に子細が書いてある。
で、環境が整ったので、Joomla2.5.58から3.5.xにアップデートをしてみた。
Administrator画面から、「Joomlaの更新」を選んで一応簡単にできる。Joomlaサイトの記述に依れば、ほとんどは大丈夫らしいが、うちはダメだった。
どうも、Joomla1.xからアップグレードでサイトを更新していると、二つのディレクトリ:
/var/www/bin/
/var/www/layouts/
が無く、これが無いとエラーになってしまう。そこで、これらのディレクトリを自分で掘ってしまうことにした。つまり、
mkdir /var/www/bin
mkdir /var/www/layouts
cd /var/www
chown apache:apache bin layouts 
をしたところ、エラーは発生せずに無事にアップグレードできました。
ああ、焦った。

2017年6月9日金曜日

Database connection error (2): Could not connect to MySQL.

Joomlaを2.5で運用している。本当は最新の3.5にしたいんだけど、サーバがCentOS6.8でデフォルトのMySQLやPHPが3.5に対応していない。そこで、MySQLを5.5に、PHPを5.6に変更してみた。
まず、MySQLは本家本元が用意してくれているリポジトリからとってくる。
yum install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm yum install yum-utils
yum-config-manager --disable mysql56-community
yum-config-manager --enable mysql55-community
yum install mysql mysql-devel mysql-server mysql-utilities
これは簡単だった。データベースがあれば、mysql_upgradeして必要なデータベースの変更を行う。失敗することもあるらしいので、データを予めダンプするなりして置くことはいうまでもなく必要。
つぎは、PHP。自分でソースからコンパイルするのも有りだけど、とりあえずメンテナーのしっかりしているところから持ってくる方が得策。で、REMIのリポジトリからとってくることにした。
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
yum install --enablerepo=remi,remi-php56 php php-devel php-mbstring php-pdo \
php-gd php-xml php-mysqlnd
これで良かったはずだったのが、Joomlaのホーム画面をブラウズする と、
Database connection error (2): Could not connect to MySQL.
が出てしまった。これはどうもmySQLへのアクセスに使うアカウントが使えない際に発生するとJoomlaの人たちが言っている。でも何もいじってないし。で、調べてみた。

mysql -uroot -p mysql -e 'select User,length(Password) from user;'
Enter password:
+----------+------------------+
| User     | length(Password) |
+----------+------------------+
| root     |               16 |
| joomla   |               16 |
| web      |                16 |
+----------+------------------+
となっていて、パスワードの長さが16だった。PHP5.5からはmySQLとのアクセスにphp-mysqlnd (mysqllnd)を使っていて、 どうも昔の短いパスワードが使えなくなったらしい。本来なら、
mysql -uroot -p mysql -e 'select User,length(Password) from user;'+----------+------------------+| User | length(Password) |+----------+------------------+| root | 41 || root | 41 |
となるらしい。これを解決するには、もし、/etc/my.cnfに"old_password=1" があるなら、0に変えて、その後リスタート。そして、パスワードを変更してやる。それでオーケー。のはず。

2017年6月1日木曜日

C++ Matrix Vector Libraries

行列とベクトルの演算に関するライブラリは、基本がNetLibのBLASで、そのAPIは同じで実装に色々工夫がされているライブラリがたくさんある。しかしながらそのインターフェースは昔ながらのサブルーチンコールになっている。
その一方、C++はそのオペレータオーバーロードという仕組みによって、行列やベクトルの演算が、まるで教科書にある数学的な書式で行うことが出来る。たとえば、
b = M * a;
のように書けば、行列Mにベクトルaを掛けて、その結果をベクトルbに代入するということになる。変なサブルーチンを呼ばなくてもいいから簡単である。
ところが、この演算をC++でやると、実行速度が極めて遅くなるという問題が起こる。それは、上記の演算は実は、
tmp = M * a;
b = tmp;
という一時的にベクトルデータを格納するtmpというインスタンスが必要となってしまうからだ。tmpが小さければ良いが、大きくなれば大問題となる。
この問題を解決したのが20年以上前に、あるカナダ人学生が考え出した、Expression Templateという方法だ。このC++独特の実装技術を用いると、tmpを使わないで済む様になる。
現在のC++の行列演算ライブラリはこの技術を用いているが、現在は更に色々な問題が発生している。 共通するのはキャッシュミスヒットによる性能の悪化である。

b = M * V

一番簡単な演算で、四則演算量は、
N * (N + N-1)
である。 これを計算時間で 割ってやると、FLOPS値が得られる。
FLOPS = 計算量 / 時間

Boost

N=1000のとき、0.118404 GFLOPSを得た。Boostでは関数の形で積算は行われるので、参考までのデータとなる。

Eigen3

N=1000のとき、3.19285 GFLOPSを得た。

Blaze

N=1000のとき、1.077 GFLOPSを得た。

BoostはETを用いていなく、更にEigen3とBlazeはSSE3などのSIMD命令を使っているので差が大きく出ている。

b = M*M*V

このかたちの演算を行うとき、問題が存在する。コンパイラは左から式を解釈していくため、まずM*Mを計算し、その後、(M*M)*Vをおこなってしまう。これを右から順に行えば、二つの行列とベクトルの演算になるので、行列と行列の演算を行ってしまうよりも遙に少ない演算量で行える。少ない方での四則演算量は、行列の長さをNxNとすると、
2 * N * (N+N-1)
となる。

Boost

Boostでは、積算は関数で行われるようになっているので、参考までにあげる。
b = prod( M, V);
b = prod( M, b);
N=1000のとき、0.114209 GFLOPSを得た。

Eigen3

N=1000のとき、0.0246804 GFLOPSを得た。

Blaze

N=1000のとき、1.11148 GFLOPSを得た。

この場合、M*Vのパフォーマンスに比べてEigen3はかなり悪い。これは、左から演算を行っているためだろう。また、Blazeは彼らの言う、Smart Expression Template技術によってこのような場合もうまく計算している事が分かる。