HPCメモ

HPC(High Performance Computing)に関連したりしなかったりすることのメモ書き

cmderでIntel CompilerとVSを使う設定

数値計算というと、大学とかに置いてあるスパコンにログインして、Linuxコマンドラインで作業してるイメージが強いかもしれませんが、時々windows上でVisualStudioとIntelコンパイラで開発してますっていう人にも出会います。*1

となると、受託開発ではやっぱりwindowsでやってねというお話をいただくこともあるんですが、いかんせんVSの起動が遅すぎるので
viでコードを書いてコマンドラインからビルドするといういつものスタイルで作業したくなるわけです。
しかし、インテルコンパイラのインストール時にもろもろ設定してくれたコマンドプロンプトは、所詮windowsのデフォルトのコマンドプロンプト上で環境変数などを設定しただけのものなので、使い難いったらありゃしない。


前置きが長くなりましたが、cmderの設定をいじって、インテルコンパイラを使える状態のcmd.exeが起動するようにしようというのが今回の目的です。
ちなみに環境はIntel Parallel Studio 2016+Visual Studio 2015+windows7な環境ですので、インストール先などは適宜読み替えてください。


まずは既存の設定の確認から

スタートメニューから「すべてのプログラム」->「Intel Parallel Studio XE 2016」->「Compiler and Performance Libraries」-> 「Command Prompt with Intel Compiler 16.0」とたどって「Intel 64 Visual Studio 2015 environment」をクリックします。


f:id:n_so5:20151202104215p:plain


プロパティ画面が開いたらリンク先欄にある文字列をコピーしておいて、cmderを起動します。
cmderのsettings画面で、「Startup」-> 「Tasks」とたどって「+」ボタンを押し右下の欄にペーストします。
後は上の方にある欄に適当に名前を付ければ完了です。


f:id:n_so5:20151202111235p:plain


cmder上で[+]ボタンの横にある下向き三角をクリックすると、メニューがずらっと出てくるので
さきほど作ったtaskを選ぶと、こんな感じでiclにパスが通った状態でコマンドプロンプトが起動します。


f:id:n_so5:20151202111651p:plain


あとは、vi+ctagsがあれば快適なコーディングができます。
ま、自由にいじっていいならcmakeでビルドするようにして、バッチファイルでも置いとくんですが・・・

*1:以前の同僚はVSしか使ったことが無いとか言ってて入社してきた時に凄いカルチャーショックを受けました

pandas+matplotlibで3D棒グラフを作る

たとえば、こんな感じの表があったとするじゃないですか。

うし ぶた とり
肉屋 580 280 300
スーパー 420 260 320

これを、エクセルに入力して、挿入->3D-縦棒と選ぶと

f:id:n_so5:20151008183105p:plain

こんな感じのかっこいい(?)グラフが作れるわけですが、これをpandas+matplotlibでやってみようというお話です。

結論から先に書くと

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.font_manager import FontProperties

df=pd.DataFrame({u"うし":[580, 420],
                 u"とり":[280, 260],
                 u"ぶた":[300, 320]},
               index=(u"肉屋", u"スーパー"))

ax=plt.figure().add_subplot(111, projection='3d')
fp=FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=10)

xpos,ypos=np.meshgrid(np.arange(len(df.index)), np.arange(len(df.columns)))
xpos=xpos.flatten()
ypos=ypos.flatten()
zpos=np.zeros(len(xpos))
dx=np.full(len(xpos), 0.05)
dy=np.full(len(ypos), 0.1)
dz=df.as_matrix().flatten()
ax.bar3d(xpos, ypos, zpos, dx, dy, dz)

ax.set_xlabel(u"お店", fontproperties=fp)
ax.set_ylabel(u"種類", fontproperties=fp)
ax.set_zlabel(u"金額", fontproperties=fp)
plt.xticks(np.arange(len(df.index)),   df.index, fontproperties=fp)
plt.yticks(np.arange(len(df.columns)), df.columns, fontproperties=fp)

plt.axis([-0.5, len(df.index)-0.5, -0.5, len(df.columns)-0.5])

plt.savefig("hoge.png")

みたいなコードになります。


公式ページのexampleを見ると、
mplot3d example code: bars3d_demo.py — Matplotlib 1.4.3 documentation
ってのがありますが、こっちは普通の棒グラフを奥行方向に重ねて並べるもののようで、今回作ろうと思っていたのとはちょっと違います。

一見関係無さそうな名前ですが、
mplot3d example code: hist3d_demo.py — Matplotlib 1.4.3 documentation
のところで使っている、bar3d()が今回のグラフに必要な関数でした。
ところがこの関数、APIドキュメントがこんな調子でまったく意味不明です。

bar3d(x, y, z, dx, dy, dz, color=u'b', zsort=u'average', *args, **kwargs)

Generate a 3D bar, or multiple bars.

When generating multiple bars, x, y, z have to be arrays. dx, dy, dz can be arrays or scalars.

color can be:

A single color value, to color all bars the same color.
An array of colors of length N bars, to color each bar independently.
An array of colors of length 6, to color the faces of the bars similarly.
An array of colors of length 6 * N bars, to color each face independently.

When coloring the faces of the boxes specifically, this is the order of the coloring:

-Z (bottom of box)
+Z (top of box)
-Y
+Y
-X
+X

Keyword arguments are passed onto Poly3DCollection()

http://matplotlib.org/mpl_toolkits/mplot3d/api.html#mpl_toolkits.mplot3d.axes3d.Axes3D.bar3d

x, y, z have to be arraysとか言われても、何の値入れりゃえんじゃーと悩んでましたが、どうやら

  • 各配列は全て同じ長さの1次元配列にする
  • i番目の棒の左下隅の頂点座標をx, y, zのi番目の要素で指定
  • i番目の棒の各軸方向の幅をdx, dy, dzのi番目の要素で指定

ということのようです。

ちなみに、この例ではx、yともに項目名なのであまり違和感は無いかもしれませんが、元々私がやってた時は2次元でパラメータを振った時の実験結果をプロットしようとしていたので、x, y, zに値を入れてからdx, dy, dzって何を入れるんだろうかと、かなりドツボにはまってました。*1

あとのところは、コードを見れば分かると思いますので、解説は省きますが

set_?label
ラベルの設定
{x,y}ticks
x/y座標の値の指定
axis
座標軸の長さ指定
savefig
グラフを画像ファイルとして保存

です。


matplotlibの全般的な話は
matplotlib入門 - りんごがでている
に助けられました。ここ読まなかったら未だドキュメントの海で溺れてたと思いますorz

あと、フォント関連の設定については
Python - matplotlibで日本語 - Qiita
を参考にさせていただきました。



そういや、pandasろくに使って無いな・・・

*1:素直にwire frameでやってればそんなにはまらなかった気がしないでもない

windowsでのpython3のセットアップ

相変わらず仕事でpythonが絡むと「python2向けで」とか、下手すると「2.6で動作すること」とか言われますが、そろそろ自作のソフトくらいはpython3へ移行しようと思い立って、まずは環境を用意することにしました。

まずは、chocolateyからpython2/3をまとめてインストールします。

>choco install python python2 -y Chocolatey v0.9.9.7
Installing the following packages:
python;python2
By installing you accept licenses for the packages.

python v3.4.3.20150501
 Get-BinRoot is going to be deprecated by v1. Many packages no longer require it since the folders no longer have versions on them.
 Downloading python 32 bit
   from 'https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi'
 Installing python...
 python has been installed.
 The install of python was successful.

python2 v2.7.10
 Get-BinRoot is going to be deprecated by v1. Many packages no longer require it since the folders no longer have versions on them.
 Warning: Old installation path “C:\Python27” detected.
 This package will continue to install python2 there unless you uninstall
 python2 from there and remove the “C:\Python27” folder. If you decide
 to do that, reinstall this package with the -force parameter and it will
 install to the Chocolatey bin root.
 Installing python2...
 python2 has been installed.
 The install of python2 was successful.

Chocolatey installed 2/2 package(s). 0 package(s) failed.
 See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).

途中で別のwindowが開いたりしますが、インストール完了後に一旦コマンドプロンプトを開き直すと

> python --version
Python 3.4.3
> C:\Python27\python.exe --version
Python 2.7.10

といった形でpython2と3が無事に動くようになりました。

続いてvirtualenvのインストール

>C:\tools\python3\Scripts\pip install virtualenv
You are using pip version 6.0.8, however version 7.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting virtualenv
  Downloading virtualenv-13.1.2-py2.py3-none-any.whl (1.7MB)
    100% |################################| 1.7MB 63kB/s
Installing collected packages: virtualenv

Successfully installed virtualenv-13.1.2

では、さっそくvirtual envを使って、python2.7用の環境を作ってみましょう。

>python -m virtualenv --python=C:\Python27\python.exe Py27
Running virtualenv with interpreter C:\Python27\python.exe
New python executable in Py27\Scripts\python.exe
Installing setuptools, pip, wheel...done.

Py27フォルダに移動して、activateすると

>cd Py27
>Scripts\activate
>python --version
Python 2.7.10

となって、無事にpython2.7の環境ができました。
この状態からdeactivateすると素の環境に戻ります。

>deactivate
>python --version
Python 3.4.3


とりあえず、2.7と3.4用の開発環境を一式作っておこう。

chefをやめてchocolateyへ

単にパッケージをインストールするだけのこんな感じのレシピをいくつか書いた後でふと気づきました。

if platform_family?('windows')
    windows_package node['hoge']['display_name'] do
      source         node['hoge']['url']
      installer_type :custom
      action         :install
      options        "/quiet"
    end
end

わざわざchefを使うまでの話でもないな・・・



というわけで、単純なインストール作業はchocolateyに
お任せすることにしました。

そうすると、今までchefでやってた作業で残るものは

  1. C:\WORKの作成
  2. 環境変数HOMEの設定
  3. gitで管理しているドットファイルの取得
  4. ssh鍵の作成
  5. フォントのインストール
  6. 環境変数PATHの設定(viとかのインストール先を追加したい)
  7. 自動起動の設定(主にautohotkey)

といったところです。

このうち、1, 2, 3, 6, 7についてはpowershellスクリプトに移行しました。
4,5は大した手間でもないので、手作業でやってます。*1



私が考えていたchefの利点というのは以下の3つでした。

  • 冪等性
  • platform independent
  • DSL

ところが、1のケースで考えると、そもそも既存のディレクトリが存在したら、ディレクトリは生成できるわけがないので、どんな手段を使うにしても冪等性を考える必要はないわけです。*2
同じように、3のケースであればgitコマンド自体が冪等性を保証してくれますし、ソフトのインストールについてもインストール済みであればwindowsインストーラが大抵は勝手に判定してくれます。

環境変数の設定はbashのexportでもsetxコマンドでも考慮してくれないので、PATHに同じディレクトリが複数回設定されるような状況が容易に起こるわけですが、この程度のことのためにchefを導入するのは、役不足でしょう。


platform依存性という観点では、そもそも設定している内容がwindows環境だから設定しないといけないという性質のものばかりなので、実際のところ、これまでの運用ではあまり活かせてませんでした。
vagrantvirtualboxみたいな、どんなOSでも入れたいソフトもあるので、こういったもののインストールはお任せしたいところなんですが、現状のchefではaptやyumdmgwindowsのような、各プラットフォームに対応するためのcookbookも準備する必要があって、少々煩わしいです。*3
あと、pythonとかnode.jsのような、重要なソフトのコミュニティcookbookがwindowsに対応していなくて、結局自分でwindows専用のcookbookを
書く羽目になるのも悲しいところです。


最後のDSLというのは、スクリプトで書き直していると重要性を痛感できるんですが、これまた環境変数の件と同じく、これだけのためにchefを導入するもんでもないなぁと感じてます。


というわけで、ほぼすべての自作cookbookは闇に葬られて、いくつかのpowershellスクリプトに生まれ変わりました。

*1:そもそも4は今までもパスフレーズの入力の時に操作する必要があったので完全に自動化できてたわけじゃないし

*2:ファイルシステムが担保していると考えれば良いのかな?

*3:Berkshelfなどで管理は自動化できるとはいえ、本来要らないものを入れられるのにはちょっと抵抗があります。

windowsの"PROGRAMFILES"環境変数

32bit windowsでは、プログラムのインストール先はたいてい"C:Program Files"ですが、64bit windowsでは、64bitプログラムは"C:Program Files"に、32bitプログラムは"C:Program Files(x86)"に分けてインストールするのがお約束になっています。

この"Program Files"ディレクトリを参照する環境変数として%PROGRAMFILES%というのがあるんですが、この環境変数は呼び出し元プログラムが32bitか64bitかによって変わるようです。

C:\WORK>\Windows\SysWOW64\cmd.exe
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\WORK>echo %PROGRAMFILES%
C:\Program Files (x86)

C:\WORK>exit

C:\WORK>\Windows\System32\cmd.exe
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\WORK>echo %PROGRAMFILES%
C:\Program Files

一瞬逆に思えるけど、System32の下にあるのが64bit版で、SysWOW64の下にあるのが、32bit版のcmd.exeです。


インストーラ無しで配布されているプログラムをインストールする(chefの)recipeで、インストール先として

"#{ENV['PROGRAMFILES']}\\hoge"

みたいなのを指定してたら、git-bashから入れるとProgram Files(x86)に入るし、コマンドプロンプトから入れるとProgram Filesに入るし大混乱になりました・・・orz


一応、こんな感じで回避してますが、そもそもインストール先を選択する時に%PROGRAMFILES%を使うのは不適切だってことですね。

if kernel['machine'] =~ /x86_64/
     default['install_to']  = "#{ENV['PROGRAMW6432']}"
else
     default['install_to']  = "#{ENV['PROGRAMFILES']}"
end

cmakeでC++ルーチンを呼び出すFortranプログラムをビルドする

自作のライブラリ(C++で作成、C、Fortranのインタフェースあり)をFortranのプログラムから呼び出すサンプルコードを書いてたんですが、CmakeList.txtの作成ではまったので、メモ

cmake fortran c++ mixedlink あたりでぐぐると、

SET_TARGET_PROPERTIESで、LINKER_LANGUAGE をCXXに設定するべし

という解決方法が定番のようです。実際にg++/gfortranの環境であればこれで問題無いんですが、intel コンパイラの場合は、この方法ではリンク時にエラーになります。


Compiling and Linking Intel® Fortran/C Programs

によると、リンク時に"-cxxlib"を渡せと書いてますが、これもうまく動作しなかったので、当面の回避策として、こんな形にしてみました。

project(hoge CXX C Fortran)
.
.
.
add_executable(huga huga.f90)
target_link_libraries(huga my_cxx_lib ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES})

要は、CXXコンパイラが暗黙的にリンクするライブラリを強制的にtarget_link_librariesで追加してるだけです。
これでPGIコンパイラとかでも動いてくれたらいいなぁ

chef -zeroでwindows用開発環境を構築(その4)

運用を始めてから気付いたことをバラバラとメモっときます。

gitでエラーになる

gitのレシピを実行すると、こんなエラーが発生する時があります。

FATAL: Errno::EIO: git[C:\WORK\unix_home] (update_home_dir::default line 10) had an error: Errno::EIO: Input/output error - CreateProcessW

ここにissueとして出てますが、gitじゃなくてgit.exeを呼ばないと発生するエラーだそうです。
git resource Errno::EIO on windows · Issue #1622 · chef/chef · GitHub
そのうち解決されると思いますが、とりあえずのワークアラウンドとしてこんな感じに修正しておきました。

if platform_family?('windows')
    git_command="git.exe"
else
    git_command="git"
end

#clone remote repo to $HOME if not exist
if ! ::File.directory?("#{ENV['HOME']}/.git")
    execute "git init" do
        command  "#{git_command} init"
        cwd      "#{ENV['HOME']}"
    end
    execute "git remote add" do
        command  "#{git_command} remote add origin #{node['update_home_directory']['repo']}"
        cwd      "#{ENV['HOME']}"
    end
end

execute "git pull" do
    command  "#{git_command} pull origin master"
    cwd      "#{ENV['HOME']}"
end
execute "git submodule" do
    command  "#{git_command} submodule update --init --recursive"
    cwd      "#{ENV['HOME']}"
end

cloneせずに、わざわざinitしてからpullしてますが、これはこのエラーとは無関係で、gitが実行される前に%HOME%\.chefディレクトリが作られてしまってgit cloneに失敗することへの対策です。

windows_packageの羃等性

githubのページに書かれているように、windows_packageに渡す名前は[コントロールパネル]->[プログラムと機能]のリストに表示されている名前と正確に一致させていないと、インストール済かどうかの判定に失敗します。
opscode-cookbooks/windows · GitHub
でもって、この名前はプログラムによってバージョン名を含むものや含まないものが混在しているので、もしバージョン番号が入っていないソフトだったら、アップデートするのが難しくなるので違う名前にしておきましょう。(うちの環境だとAmazon KindleとかcourvusSKKとかがバージョン番号が無いです)

ログオン時に実行させる

スタートアップに追加するのは、専用のリソースが用意されていて、次のようなコードで登録できます。

windows_auto_run "autohotkey" do
    program node['autohotkey']['program_name']
    not_if  {Registry.value_exists?(AUTO_RUN_KEY, "autohotkey")}
    action  :create
end

ショートカットの追加

ショートカットも専用のリソースがあって、こんな感じで追加できます。

windows_shortcut "#{ENV['USERPROFILE']}\\Desktop\\gvim.lnk" do
    target       exe_path
    description  "gvim"
    action       :create
end

本当はスタートメニューとかタスクバーに登録したいんですが、こっちのやり方は分からず・・・

ファイルの関連付け変更

ファイルの関連付けは、コマンドラインからassocやftypeコマンドを使うのが正しいやり方だと思いますが、面倒なのでレジストリを直接いじります。しかし、ぐぐってみると昔のkeyも有効なようで

"HKEY_CURRENT_USER\\Software\\Classes\\.#{ext}\\shell\\open\\command"

に登録するパターンと

"HKEY_CURRENT_USER\\Software\\Classes\\#{ext}_auto_file\\shell\\open\\command"

に登録するパターンのどちらでも良いようです。(#{ext}は拡張子)

うちの環境でテストした限りでは、

  • 後者の方が優先
  • エクスプローラGUIから設定する画面(ファイルを開くプログラムの選択)には後者の方法で登録しないと表示されない

という問題があるので、後者のkeyを使っています。

具体的にはgvimのレシピの中でこんな感じにしてます。

%w{rb py js txt log c C cpp h f F f90 F90}.each do |ext|
    registry_key "set file type assocication by auto_file #{ext}" do
        key    "HKCU\\Software\\Classes\\#{ext}_auto_file\\shell\\open\\command"
        values [{
            :name => "",
            :type => :string,
            :data => "#{exe_path} %1"
        }]
        recursive true
    end
end