AmberTools13をCentOS 6.4にインストール

AmberTools13を以下の場所からダウンロードしてきてインストールしました。名前や所属等を聞かれますがすぐにダウンロードできます。古いバージョンが欲しい場合は下にリンクがあります。

http://ambermd.org/
http://ambermd.org/AmberTools-get.html

やり方は以下のサイトほぼそのままです。Ubuntu等のDebian系は詳細に説明があります。

http://jswails.wikidot.com/installing-amber12-and-ambertools-13

ではインストールをしてみます。
インストールの前に、依存関係のファイルを入れておくと良いです。

yum install tcsh
yum install gcc gcc-c++ gcc-gfortran
yum install flex flex-devel
yum install libX11 libX11-devel
yum install tcsh
yum install zlib zlib-devel
yum install bzip2 bzip2-devel # ここまで公式サイトに記述のある必須ライブラリ
yum install libXt libXt-devel libXext-devel libICE-devel libSM-devel # configure時のエラー対処
yum install libXdmcp-devel # make install時のエラー対処
tar xjvf AmberTools13.tar.bz2
# Amber本体を持っている場合は、
# tar jxvf Amber12.tar.bz2
# をすると、amber12フォルダに必要なファイルが展開される。
# コンパイル方法は有り無し関係なく同じ。
cd amber12
./configure gnu -noamber
make install

これだけ。bin以下にツール群が入っています。
何かエラーが出たら、その英文を良く読んで対処しましょう。

ビット演算のサンプル(2)

前回のものはibsetやibclrが無かったので、改めて作りました。
C言語でいうsizeof関数の代わりにfortranではsize関数がありますが、配列の長さを確かめることにしか使えません。bit_sizeを使えばデバッグに役立ちそうだと思いました。

! bit operations
program main
    implicit none

    integer(kind=1) :: bbb, ccc

    write(*, '(a20,2x,i3)') "bit size            ", bit_size(bbb)
    write(*,*)

    ! ---------------------------
    write(*,'(a)') "--- Bit Operation ---"
    write(*, '(a20,2x,$)') "initial set 0       "
    bbb = 0
    call output_bit(bbb)

    write(*, '(a20,2x,$)') "set bit 0,2,3       "
    bbb = ibset(bbb, 0)
    bbb = ibset(bbb, 2)
    bbb = ibset(bbb, 3)
    call output_bit(bbb)

    write(*, '(a20,2x,$)') "clear bit 0         "
    bbb = ibclr(bbb, 0)
    call output_bit(bbb)

    write(*, '(a20,2x,$)') "shift bit 2         "
    bbb = ishft(bbb, 2)
    call output_bit(bbb)

    write(*, '(a20,2x,$)') "shift bit -1        "
    bbb = ishft(bbb, -1)
    call output_bit(bbb)
    
    write(*,*)

    ! ---------------------------
    write(*, '(a20,2x,$)') "initial 0x05        "
    bbb = 5
    call output_bit(bbb)

    write(*, '(a20,2x,$)') "initial 0x03        "
    bbb = 3
    call output_bit(bbb)

    bbb = 5; ccc = 3
    write(*, '(a20,2x,$)') "0x05 and 0x03       "
    bbb = iand(bbb, ccc)
    call output_bit(bbb)

    bbb = 5; ccc = 3
    write(*, '(a20,2x,$)') "0x05 or  0x03       "
    bbb = ior(bbb, ccc)
    call output_bit(bbb)

    bbb = 5; ccc = 3
    write(*, '(a20,2x,$)') "0x05 xor 0x03       "
    bbb = ieor(bbb, ccc)
    call output_bit(bbb)

    bbb = 5
    write(*, '(a20,2x,$)') "not 0x05            "
    bbb = not(bbb)
    call output_bit(bbb)

    ! ---------------------------
    write(*,'(a)') "--- Bit Operation ---"
    write(*, '(a20,2x,$)') "shift bit -1        "
    bbb = ishft(bbb, -1)
    call output_bit(bbb)

contains
subroutine output_bit(b)
    integer(kind=1) :: b

    write(*,'(a, z2.2, 2x, a, b8.8)') "0x", b, "0b", b
end subroutine output_bit
end program main

結果

bit size                8
 
--- Bit Operation ---
initial set 0       0x00  0b00000000
set bit 0,2,3       0x0D  0b00001101
clear bit 0         0x0C  0b00001100
shift bit 2         0x30  0b00110000
shift bit -1        0x18  0b00011000
 
initial 0x05        0x05  0b00000101
initial 0x03        0x03  0b00000011
0x05 and 0x03       0x01  0b00000001
0x05 or  0x03       0x07  0b00000111
0x05 xor 0x03       0x06  0b00000110
not 0x05            0xFA  0b11111010
--- Bit Operation ---
shift bit -1        0x7D  0b01111101

ビット演算のサンプル

Fortranでビット演算をするサンプルスクリプトを作りました。余りソースが無いので、サンプルを動かしながら動作を確かめた方が理解が早そう。

program main
    implicit none
    integer :: i, j, b1, b2, h1, h2, o1, o2

    o1 = 5
    o2 = 21
    b1 = b'00000101'
    b2 = b'00010101'
    h1 = x'05'
    h2 = x'15'
    
    write(*, *) "octal output"
    write(*, '(o4, o4, o4)') o1, o2, o1+o2
    write(*, '(o4, o4, o4)') b1, b2, b1+b2
    write(*, '(o4, o4, o4)') h1, h2, h1+h2

    write(*,*) "hexadecimal output"
    write(*, '(z4, z4, z4)') o1, o2, o1+o2
    write(*, '(z4, z4, z4)') b1, b2, b1+b2
    write(*, '(z4, z4, z4)') h1, h2, h1+h2

    write(*,*) "bit calculation for 0x05 and 0x15"
    write(*, '(a5, z4)') "AND", iand(b1, b2)
    write(*, '(a5, z4)') "OR", ior(b1, b2)
    write(*, '(a5, z4)') "XOR", ieor(b1, b2)
    write(*, '(a5, z16)') "NOT", not(b1)

    write(*, '(1x,a,$)') "(i,j) |"
    do i = 0, 1
        do j = 0, 1
            write(*, '(1x, a,i1,a,i1,a, 1x,$)') &
                & "(", i, ",", j, ")"
        end do
    end do
    write(*,*)

    write(*, '(1x,a,$)') " AND  |"
    do i = 0, 1
        do j = 0, 1
            write(*, '(3x, i1, a,$)') iand(i,j), "  "
        end do
    end do
    write(*,*)

    write(*, '(1x,a,$)') " OR   |"
    do i = 0, 1
        do j = 0, 1
            write(*, '(3x, i1, a,$)') ior(i,j), "  "
        end do
    end do
    write(*,*)

    write(*, '(1x,a,$)') " XOR  |"
    do i = 0, 1
        do j = 0, 1
            write(*, '(3x, i1, a,$)') ieor(i,j), "  "
        end do
    end do
    write(*,*)

end program main

結果

 octal output
   5  25  32
   5  25  32
   5  25  32
 hexadecimal output
   5  15  1A
   5  15  1A
   5  15  1A
 bit calculation for 0x05 and 0x15
  AND   5
   OR  15
  XOR  10
  NOT        FFFFFFFA
 (i,j) | (0,0) (0,1) (1,0) (1,1) 
  AND  |   0     0     0     1   
  OR   |   0     1     1     1   
  XOR  |   0     1     1     0   

反復解法ライブラリLisのWindows 64bit対応化

国産の有名なライブラリである反復解法ライブラリLisをWindowsアプリケーションで使用した際に躓いたのでメモ。
http://www.ssisc.org/lis/index.ja.html

以下の環境でWindows版のLisをコンパイルして使用すると、メモリのアクセス違反が頻発して使い物になりませんでした。以下、アプリのコンパイル環境です。

  • 自作アプリケーションはFortran
  • integerは4 byte、realは8 byteをkindで定義して使用
  • assume:underscoreとnames:lowercaseを使用
  • MPIやOpenMPは使用しない

この状態でLisを同じプロジェクトに組み込み、依存関係を設定してコンパイルすると、コンパイルは通りますが、実行途中で止まります。試行錯誤の途中でエラーの内容は色々ましたが、create_matrixやsolve_matrixなど様々なところで止まります。

原因は、これ。
http://d.hatena.ne.jp/kohtani/20061225/p1

LinuxはLP64でありlong型が64bitなのに対し、WindowsLLP64を採用していてlong型は32bitになっている。Lisの中でlongが使用されているので、Linuxの64bitで動作しているものがそのままWindows64bitで使用できないことになる。

解決方法としては、必ず64bitになるlong long型を使用すればいい。ただし、long long型は32bitマシンでも64bit整数としてみなされるため、整数型をOSのbitに合わせるためには、マクロを用いなければならない。非常に面倒である。誰だこんな仕様にしたのは。

というわけで、試行錯誤しながらLisをWindows64bit対応にしてみた。

Linux上やWindowコンソール上でconfigureをやる場合に、--enable-fortranと--enable-intelを付けているという想定。

LisをVisual Studio上でコンパイルする場合は、C, C++のコードと、Fortranのコードを別プロジェクトとして登録する必要がある。FortranはVisual Fortranが入っている前提。Fortranのプロジェクトの依存関係で、C, C++のプロジェクトを指定してあげる。
Visual Studioのプロパティから、プリプロセッサの設定のところを開く。「プリプロセッサー定義」のところに、USE_FORTRANとHAVE_CONFIG_WIN_Hを追加する。
USE_FORTRAN定義は、そのままFortranのコードを生成するためのフラグ。
HAVE_CONFIG_WIN_Hは、windows用のヘッダーを読み込むためのフラグ。
もしここにWIN32という定義があれば消す必要がある。WIN32が付いているとWindows用の分岐とともに、32bit用のコード書き換えが起きてしまう。Windows用の書き換えはそんなに難しくないので、手動でやってしまおう。時間計測のヘッダーが違う。それだけ。

具体的なソースコードの書き換えを以下で説明する。

// lis_config_win.h 15行目
//#define USE_QUAD_PRECISION 1 // コメントアウト
// lis_fortran.h 31行目
// long型をlong long型に変更
typedef long long		LIS_MATRIX_F;
typedef long long		LIS_VECTOR_F;
typedef long long		LIS_SOLVER_F;
typedef long long		LIS_ESOLVER_F;
typedef long long		LIS_SCALAR_F;

// 44行目 long long型に変更
#define LIS_V2P(a)	(*(long long *)(a))
#define LIS_P2V(a)	((long long)(a))
// lis_times.c 47行目
	//#include <sys/time.h> // これをコメントアウト
	#include <windows.h> // 追加

以上の変更を行ってからコンパイルすると上手くいきました。
lis_config.hのSIZEOF_を色々いじってみたけど、あんまりソースコードから呼び出されてないので意味が無いようです。SIZEOF_VOID_Pは8になっていると勝手にintegerが64bit精度になってしまったりしてcとfortranの繋ぎでエラーになってしまいます。

補足

ちなみに、私のアプリケーションはFortranの関数名呼び出しに、assume:underscoreとnames:lowercaseを用いていたので、小文字+_という関数名が必要となる。だが、Lisの標準では大文字でアンダースコア無しの関数渡し方法を採用しているのでその辺を変更する必要がある。

// lis_config_win.h
// 6行目
#define F77_FUNC(name,NAME) name // 小文字に変更
// 9行目
#define F77_FUNC_(name,NAME) name // 小文字に変更
// lis_fortran.h 49行目から187行目にかけて
// 全ての関数にアンダースコアを追加する(これよりもっといい方法があるかも)
/**************/
/* MATRIX     */
/**************/
#define lis_matrix_create_f F77_FUNC_(lis_matrix_create_f_, LIS_MATRIX_CREATE_F) 
#define lis_matrix_duplicate_f F77_FUNC_(lis_matrix_duplicate_f_, LIS_MATRIX_DUPLICATE_F) 
#define lis_matrix_destroy_f F77_FUNC_(lis_matrix_destroy_f_, LIS_MATRIX_DESTROY_F) 
#define lis_matrix_set_size_f F77_FUNC_(lis_matrix_set_size_f_, LIS_MATRIX_SET_SIZE_F) 
#define lis_matrix_get_size_f F77_FUNC_(lis_matrix_get_size_f_, LIS_MATRIX_GET_SIZE_F) 
#define lis_matrix_get_range_f F77_FUNC_(lis_matrix_get_range_f_, LIS_MATRIX_GET_RANGE_F) 
#define lis_matrix_set_value_f F77_FUNC_(lis_matrix_set_value_f_, LIS_MATRIX_SET_VALUE_F) 
#define lis_matrix_get_type_f F77_FUNC_(lis_matrix_get_type_f_, LIS_MATRIX_GET_TYPE_F) 
#define lis_matrix_set_type_f F77_FUNC_(lis_matrix_set_type_f_, LIS_MATRIX_SET_TYPE_F)
#define lis_matrix_set_csr_f F77_FUNC_(lis_matrix_set_csr_f_, LIS_MATRIX_SET_CSR_F)
#define lis_matrix_set_csc_f F77_FUNC_(lis_matrix_set_csc_f_, LIS_MATRIX_SET_CSC_F)
#define lis_matrix_set_msr_f F77_FUNC_(lis_matrix_set_msr_f_, LIS_MATRIX_SET_MSR_F)
#define lis_matrix_set_dia_f F77_FUNC_(lis_matrix_set_dia_f_, LIS_MATRIX_SET_DIA_F)
#define lis_matrix_set_ell_f F77_FUNC_(lis_matrix_set_ell_f_, LIS_MATRIX_SET_ELL_F)
#define lis_matrix_set_jad_f F77_FUNC_(lis_matrix_set_jad_f_, LIS_MATRIX_SET_JAD_F)
#define lis_matrix_set_bsr_f F77_FUNC_(lis_matrix_set_bsr_f_, LIS_MATRIX_SET_BSR_F)
#define lis_matrix_set_bsc_f F77_FUNC_(lis_matrix_set_bsc_f_, LIS_MATRIX_SET_BSC_F)
#define lis_matrix_set_coo_f F77_FUNC_(lis_matrix_set_coo_f_, LIS_MATRIX_SET_COO_F)
#define lis_matrix_set_dns_f F77_FUNC_(lis_matrix_set_dns_f_, LIS_MATRIX_SET_DNS_F)
#define lis_matrix_set_vbr_f F77_FUNC_(lis_matrix_set_vbr_f_, LIS_MATRIX_SET_VBR_F)
#define lis_matrix_assemble_f F77_FUNC_(lis_matrix_assemble_f_, LIS_MATRIX_ASSEMBLE_F) 
#define lis_matrix_is_assembled_f F77_FUNC_(lis_matrix_is_assembled_f_, LIS_MATRIX_IS_ASSEMBLED_F) 
#define lis_matrix_malloc_f F77_FUNC_(lis_matrix_malloc_f_, LIS_MATRIX_MALLOC_F)
#define lis_matrix_malloc_csr_f F77_FUNC_(lis_matrix_malloc_csr_f_, LIS_MATRIX_MALLOC_CSR_F)
#define lis_matrix_malloc_csc_f F77_FUNC_(lis_matrix_malloc_csc_f_, LIS_MATRIX_MALLOC_CSC_F)
#define lis_matrix_malloc_bsr_f F77_FUNC_(lis_matrix_malloc_bsr_f_, LIS_MATRIX_MALLOC_BSR_F)
#define lis_matrix_malloc_msr_f F77_FUNC_(lis_matrix_malloc_msr_f_, LIS_MATRIX_MALLOC_MSR_F)
#define lis_matrix_malloc_ell_f F77_FUNC_(lis_matrix_malloc_ell_f_, LIS_MATRIX_MALLOC_ELL_F)
#define lis_matrix_malloc_jad_f F77_FUNC_(lis_matrix_malloc_jad_f_, LIS_MATRIX_MALLOC_JAD_F)
#define lis_matrix_malloc_dia_f F77_FUNC_(lis_matrix_malloc_dia_f_, LIS_MATRIX_MALLOC_DIA_F)
#define lis_matrix_malloc_bsc_f F77_FUNC_(lis_matrix_malloc_bsc_f_, LIS_MATRIX_MALLOC_BSC_F)
#define lis_matrix_malloc_vbr_f F77_FUNC_(lis_matrix_malloc_vbr_f_, LIS_MATRIX_MALLOC_VBR_F)
#define lis_matrix_malloc_coo_f F77_FUNC_(lis_matrix_malloc_coo_f_, LIS_MATRIX_MALLOC_COO_F)
#define lis_matrix_malloc_dns_f F77_FUNC_(lis_matrix_malloc_dns_f_, LIS_MATRIX_MALLOC_DNS_F)
#define lis_matrix_convert_f F77_FUNC_(lis_matrix_convert_f_, LIS_MATRIX_CONVERT_F)
#define lis_matrix_copy_f F77_FUNC_(lis_matrix_copy_f_, LIS_MATRIX_COPY_F)
#define lis_matrix_scaling_f F77_FUNC_(lis_matrix_scaling_f_, LIS_MATRIX_SCALING_F)
#define lis_matrix_get_diagonal_f F77_FUNC_(lis_matrix_get_diagonal_f_, LIS_MATRIX_GET_DIAGONAL_F)
#define lis_matrix_set_blocksize_f F77_FUNC_(lis_matrix_set_blocksize_f_, LIS_MATRIX_SET_BLOCKSIZE_F)


/**************/
/* VECTOR     */
/**************/
#define lis_vector_create_f F77_FUNC_(lis_vector_create_f_, LIS_VECTOR_CREATE_F) 
#define lis_vector_duplicate_f F77_FUNC_(lis_vector_duplicate_f_, LIS_VECTOR_DUPLICATE_F) 
#define lis_vector_destroy_f F77_FUNC_(lis_vector_destroy_f_, LIS_VECTOR_DESTROY_F) 
#define lis_vector_set_size_f F77_FUNC_(lis_vector_set_size_f_, LIS_VECTOR_SET_SIZE_F) 
#define lis_vector_get_size_f F77_FUNC_(lis_vector_get_size_f_, LIS_VECTOR_GET_SIZE_F) 
#define lis_vector_get_range_f F77_FUNC_(lis_vector_get_range_f_, LIS_VECTOR_GET_RANGE_F) 
#define lis_vector_set_value_f F77_FUNC_(lis_vector_set_value_f_, LIS_VECTOR_SET_VALUE_F) 
#define lis_vector_set_values_f F77_FUNC_(lis_vector_set_values_f_, LIS_VECTOR_SET_VALUES_F) 
#define lis_vector_set_values2_f F77_FUNC_(lis_vector_set_values2_f_, LIS_VECTOR_SET_VALUES2_F) 
#define lis_vector_get_value_f F77_FUNC_(lis_vector_get_value_f_, LIS_VECTOR_GET_VALUE_F) 
#define lis_vector_get_values_f F77_FUNC_(lis_vector_get_values_f_, LIS_VECTOR_GET_VALUES_F) 
#define lis_vector_scatter_f F77_FUNC_(lis_vector_scatter_f_, LIS_VECTOR_SCATTER_F) 
#define lis_vector_gather_f F77_FUNC_(lis_vector_gather_f_, LIS_VECTOR_GATHER_F) 
#define lis_vector_print_f F77_FUNC_(lis_vector_print_f_, LIS_VECTOR_PRINT_F) 
#define lis_vector_set_all_f F77_FUNC_(lis_vector_set_all_f_, LIS_VECTOR_SET_ALL_F) 
#define lis_vector_axpy_f F77_FUNC_(lis_vector_axpy_f_, LIS_VECTOR_AXPY_F) 
#define lis_vector_xpay_f F77_FUNC_(lis_vector_xpay_f_, LIS_VECTOR_XPAY_F) 
#define lis_vector_axpyz_f F77_FUNC_(lis_vector_axpyz_f_, LIS_VECTOR_AXPYZ_F) 
#define lis_vector_copy_f F77_FUNC_(lis_vector_copy_f_, LIS_VECTOR_COPY_F) 
#define lis_vector_scale_f F77_FUNC_(lis_vector_scale_f_, LIS_VECTOR_SCALE_F) 
#define lis_vector_pmul_f F77_FUNC_(lis_vector_pmul_f_, LIS_VECTOR_PMUL_F) 
#define lis_vector_pdiv_f F77_FUNC_(lis_vector_pdiv_f_, LIS_VECTOR_PDIV_F) 
#define lis_vector_abs_f F77_FUNC_(lis_vector_abs_f_, LIS_VECTOR_ABS_F) 
#define lis_vector_reciprocal_f F77_FUNC_(lis_vector_reciprocal_f_, LIS_VECTOR_RECIPROCAL_F) 
#define lis_vector_shift_f F77_FUNC_(lis_vector_shift_f_, LIS_VECTOR_SHIFT_F) 
#define lis_vector_dot_f F77_FUNC_(lis_vector_dot_f_, LIS_VECTOR_DOT_F) 
#define lis_vector_nrm1_f F77_FUNC_(lis_vector_nrm1_f_, LIS_VECTOR_NRM1_F) 
#define lis_vector_nrm2_f F77_FUNC_(lis_vector_nrm2_f_, LIS_VECTOR_NRM2_F) 
#define lis_vector_nrmi_f F77_FUNC_(lis_vector_nrmi_f_, LIS_VECTOR_NRMI_F) 
#define lis_vector_sum_f F77_FUNC_(lis_vector_sum_f_, LIS_VECTOR_SUM_F) 
#define lis_vector_is_null_f F77_FUNC_(lis_vector_is_null_f_, LIS_VECTOR_IS_NULL_F) 
/**************/
/* SOLVER     */
/**************/
#define lis_solver_create_f F77_FUNC_(lis_solver_create_f_, LIS_SOLVER_CREATE_F) 
#define lis_solver_destroy_f F77_FUNC_(lis_solver_destroy_f_, LIS_SOLVER_DESTROY_F) 
#define lis_solve_f F77_FUNC_(lis_solve_f_, LIS_SOLVE_F) 
#define lis_solver_set_option_f F77_FUNC_(lis_solver_set_option_f_, LIS_SOLVER_SET_OPTION_F) 
#define lis_solver_get_iters_f F77_FUNC_(lis_solver_get_iters_f_, LIS_SOLVER_GET_ITERS_F) 
#define lis_solver_get_itersex_f F77_FUNC_(lis_solver_get_itersex_f_, LIS_SOLVER_GET_ITERSEX_F) 
#define lis_solver_get_time_f F77_FUNC_(lis_solver_get_time_f_, LIS_SOLVER_GET_TIME_F) 
#define lis_solver_get_timeex_f F77_FUNC_(lis_solver_get_timeex_f_, LIS_SOLVER_GET_TIMEEX_F) 
#define lis_solver_get_residualnorm_f F77_FUNC_(lis_solver_get_residualnorm_f_, LIS_SOLVER_GET_RESIDUALNORM_F) 
#define lis_solver_get_rhistory_f F77_FUNC_(lis_solver_get_rhistory_f_, LIS_SOLVER_GET_RHISTORY_F) 
#define lis_solver_get_solver_f F77_FUNC_(lis_solver_get_solver_f_, LIS_SOLVER_GET_SOLVER_F) 
#define lis_solver_get_precon_f F77_FUNC_(lis_solver_get_precon_f_, LIS_SOLVER_GET_PRECON_F) 
#define lis_solver_get_solvername_f F77_FUNC_(lis_solver_get_solvername_f_, LIS_SOLVER_GET_SOLVERNAME_F) 
#define lis_solver_get_preconname_f F77_FUNC_(lis_solver_get_preconname_f_, LIS_SOLVER_GET_PRECONNAME_F) 
#define lis_solver_set_optionC_f F77_FUNC_(lis_solver_set_optionc_f_, LIS_SOLVER_SET_OPTIONC_F) 
/**************/
/* ESOLVER     */
/**************/
#define lis_esolver_create_f F77_FUNC_(lis_esolver_create_f_, LIS_ESOLVER_CREATE_F) 
#define lis_esolver_destroy_f F77_FUNC_(lis_esolver_destroy_f_, LIS_ESOLVER_DESTROY_F) 
#define lis_esolve_f F77_FUNC_(lis_esolve_f_, LIS_ESOLVE_F) 
#define lis_esolver_set_option_f F77_FUNC_(lis_esolver_set_option_f_, LIS_ESOLVER_SET_OPTION_F) 
#define lis_esolver_get_iters_f F77_FUNC_(lis_esolver_get_iters_f_, LIS_ESOLVER_GET_ITERS_F) 
#define lis_esolver_get_itersex_f F77_FUNC_(lis_esolver_get_itersex_f_, LIS_ESOLVER_GET_ITERSEX_F) 
#define lis_esolver_get_time_f F77_FUNC_(lis_esolver_get_time_f_, LIS_ESOLVER_GET_TIME_F) 
#define lis_esolver_get_timeex_f F77_FUNC_(lis_esolver_get_timeex_f_, LIS_ESOLVER_GET_TIMEEX_F) 
#define lis_esolver_get_evalues_f F77_FUNC_(lis_esolver_get_evalues_f_, LIS_ESOLVER_GET_EVALUES_F)
#define lis_esolver_get_evectors_f F77_FUNC_(lis_esolver_get_evectors_f_, LIS_ESOLVER_GET_EVECTORS_F) 
#define lis_esolver_get_residualnorm_f F77_FUNC_(lis_esolver_get_residualnorm_f_, LIS_ESOLVER_GET_RESIDUALNORM_F) 
#define lis_esolver_get_rhistory_f F77_FUNC_(lis_esolver_get_rhistory_f_, LIS_ESOLVER_GET_RHISTORY_F) 
#define lis_esolver_get_esolver_f F77_FUNC_(lis_esolver_get_esolver_f_, LIS_ESOLVER_GET_ESOLVER_F) 
#define lis_esolver_get_esolvername_f F77_FUNC_(lis_esolver_get_esolvername_f_, LIS_ESOLVER_GET_ESOLVERNAME_F) 
#define lis_esolver_set_optionC_f F77_FUNC_(lis_esolver_set_optionc_f_, LIS_ESOLVER_SET_OPTIONC_F) 
/**************/
/* MATVEC     */
/**************/
#define lis_matvec_f F77_FUNC_(lis_matvec_f_, LIS_MATVEC_F) 
#define lis_matvect_f F77_FUNC_(lis_matvect_f_, LIS_MATVECT_F) 
/**************/
/* SYSTEM     */
/**************/
#define lis_set_comm_world_f F77_FUNC_(lis_set_comm_world_f_, LIS_SET_COMM_WORLD_F)
#define lis_finitialize_f F77_FUNC_(lis_finitialize_f_, LIS_FINITIALIZE_F) 
#define lis_finalize_f F77_FUNC_(lis_finalize_f_, LIS_FINALIZE_F) 
#define lis_wtime_f F77_FUNC_(lis_wtime_f , LIS_WTIME_F)
#define CHKERR_f F77_FUNC_(chkerr_f_, CHKERR_F) 
#define lis_set_argv_begin_f F77_FUNC_(lis_set_argv_begin_f_, LIS_SET_ARGV_BEGIN_F) 
#define lis_set_argv_f F77_FUNC_(lis_set_argv_f_, LIS_SET_ARGV_F) 
#define lis_set_argv_end_f F77_FUNC_(lis_set_argv_end_f_, LIS_SET_ARGV_END_F) 
#define lis_arg2args_f F77_FUNC_(lis_arg2args_f_, LIS_ARG2ARGS_F) 
#define lis_input_f F77_FUNC_(lis_input_f_, LIS_INPUT_F)
#define lis_input_matrix_f F77_FUNC_(lis_input_matrix_f_, LIS_INPUT_MATRIX_F)
#define lis_input_vector_f F77_FUNC_(lis_input_vector_f_, LIS_INPUT_VECTOR_F)
#define lis_output_f F77_FUNC_(lis_output_f_, LIS_OUTPUT_F) 
#define lis_output_matrix_f F77_FUNC_(lis_output_matrix_f_, LIS_OUTPUT_MATRIX_F) 
#define lis_output_vector_f F77_FUNC_(lis_output_vector_f_, LIS_OUTPUT_VECTOR_F) 
#define lis_solver_output_rhistory_f F77_FUNC_(lis_solver_output_rhistory_f_, LIS_SOLVER_OUTPUT_RHISTORY_F) 
#define lis_esolver_output_rhistory_f F77_FUNC_(lis_esolver_output_rhistory_f_, LIS_ESOLVER_OUTPUT_RHISTORY_F) 

追記

これだけじゃ不十分ぽい。結果がおかしいようなので、簡単な例で検証する必要がありそう。

反復解法ライブラリLisのWindows 64bit対応化

国産の有名なライブラリである反復解法ライブラリLisをWindowsアプリケーションで使用した際に躓いたのでメモ。
http://www.ssisc.org/lis/index.ja.html

以下の環境でWindows版のLisをコンパイルして使用すると、メモリのアクセス違反が頻発して使い物になりませんでした。以下、アプリのコンパイル環境です。

  • 自作アプリケーションはFortran
  • integerは4 byte、realは8 byteをkindで定義して使用
  • assume:underscoreとnames:lowercaseを使用
  • MPIやOpenMPは使用しない

この状態でLisを同じプロジェクトに組み込み、依存関係を設定してコンパイルすると、コンパイルは通りますが、実行途中で止まります。試行錯誤の途中でエラーの内容は色々ましたが、create_matrixやsolve_matrixなど様々なところで止まります。

原因は、これ。
http://d.hatena.ne.jp/kohtani/20061225/p1

LinuxはLP64でありlong型が64bitなのに対し、WindowsLLP64を採用していてlong型は32bitになっている。Lisの中でlongが使用されているので、Linuxの64bitで動作しているものがそのままWindows64bitで使用できないことになる。

解決方法としては、必ず64bitになるlong long型を使用すればいい。ただし、long long型は32bitマシンでも64bit整数としてみなされるため、整数型をOSのbitに合わせるためには、マクロを用いなければならない。非常に面倒である。誰だこんな仕様にしたのは。

というわけで、試行錯誤しながらLisをWindows64bit対応にしてみた。

Linux上やWindowコンソール上でconfigureをやる場合に、--enable-fortranと--enable-intelを付けているという想定。

LisをVisual Studio上でコンパイルする場合は、C, C++のコードと、Fortranのコードを別プロジェクトとして登録する必要がある。FortranはVisual Fortranが入っている前提。Fortranのプロジェクトの依存関係で、C, C++のプロジェクトを指定してあげる。
Visual Studioのプロパティから、プリプロセッサの設定のところを開く。「プリプロセッサー定義」のところに、USE_FORTRANとHAVE_CONFIG_WIN_Hを追加する。
USE_FORTRAN定義は、そのままFortranのコードを生成するためのフラグ。
HAVE_CONFIG_WIN_Hは、windows用のヘッダーを読み込むためのフラグ。
もしここにWIN32という定義があれば消す必要がある。WIN32が付いているとWindows用の分岐とともに、32bit用のコード書き換えが起きてしまう。Windows用の書き換えはそんなに難しくないので、手動でやってしまおう。時間計測のヘッダーが違う。それだけ。

具体的なソースコードの書き換えを以下で説明する。

// lis_config_win.h 15行目
//#define USE_QUAD_PRECISION 1 // コメントアウト
// lis_fortran.h 31行目
// long型をlong long型に変更
typedef long long		LIS_MATRIX_F;
typedef long long		LIS_VECTOR_F;
typedef long long		LIS_SOLVER_F;
typedef long long		LIS_ESOLVER_F;
typedef long long		LIS_SCALAR_F;

// 44行目 long long型に変更
#define LIS_V2P(a)	(*(long long *)(a))
#define LIS_P2V(a)	((long long)(a))
// lis_times.c 47行目
	//#include <sys/time.h> // これをコメントアウト
	#include <windows.h> // 追加

以上の変更を行ってからコンパイルすると上手くいきました。
lis_config.hのSIZEOF_を色々いじってみたけど、あんまりソースコードから呼び出されてないので意味が無いようです。SIZEOF_VOID_Pは8になっていると勝手にintegerが64bit精度になってしまったりしてcとfortranの繋ぎでエラーになってしまいます。

補足

ちなみに、私のアプリケーションはFortranの関数名呼び出しに、assume:underscoreとnames:lowercaseを用いていたので、小文字+_という関数名が必要となる。だが、Lisの標準では大文字でアンダースコア無しの関数渡し方法を採用しているのでその辺を変更する必要がある。

// lis_config_win.h
// 6行目
#define F77_FUNC(name,NAME) name // 小文字に変更
// 9行目
#define F77_FUNC_(name,NAME) name // 小文字に変更
// lis_fortran.h 49行目から187行目にかけて
// 全ての関数にアンダースコアを追加する(これよりもっといい方法があるかも)
/**************/
/* MATRIX     */
/**************/
#define lis_matrix_create_f F77_FUNC_(lis_matrix_create_f_, LIS_MATRIX_CREATE_F) 
#define lis_matrix_duplicate_f F77_FUNC_(lis_matrix_duplicate_f_, LIS_MATRIX_DUPLICATE_F) 
#define lis_matrix_destroy_f F77_FUNC_(lis_matrix_destroy_f_, LIS_MATRIX_DESTROY_F) 
#define lis_matrix_set_size_f F77_FUNC_(lis_matrix_set_size_f_, LIS_MATRIX_SET_SIZE_F) 
#define lis_matrix_get_size_f F77_FUNC_(lis_matrix_get_size_f_, LIS_MATRIX_GET_SIZE_F) 
#define lis_matrix_get_range_f F77_FUNC_(lis_matrix_get_range_f_, LIS_MATRIX_GET_RANGE_F) 
#define lis_matrix_set_value_f F77_FUNC_(lis_matrix_set_value_f_, LIS_MATRIX_SET_VALUE_F) 
#define lis_matrix_get_type_f F77_FUNC_(lis_matrix_get_type_f_, LIS_MATRIX_GET_TYPE_F) 
#define lis_matrix_set_type_f F77_FUNC_(lis_matrix_set_type_f_, LIS_MATRIX_SET_TYPE_F)
#define lis_matrix_set_csr_f F77_FUNC_(lis_matrix_set_csr_f_, LIS_MATRIX_SET_CSR_F)
#define lis_matrix_set_csc_f F77_FUNC_(lis_matrix_set_csc_f_, LIS_MATRIX_SET_CSC_F)
#define lis_matrix_set_msr_f F77_FUNC_(lis_matrix_set_msr_f_, LIS_MATRIX_SET_MSR_F)
#define lis_matrix_set_dia_f F77_FUNC_(lis_matrix_set_dia_f_, LIS_MATRIX_SET_DIA_F)
#define lis_matrix_set_ell_f F77_FUNC_(lis_matrix_set_ell_f_, LIS_MATRIX_SET_ELL_F)
#define lis_matrix_set_jad_f F77_FUNC_(lis_matrix_set_jad_f_, LIS_MATRIX_SET_JAD_F)
#define lis_matrix_set_bsr_f F77_FUNC_(lis_matrix_set_bsr_f_, LIS_MATRIX_SET_BSR_F)
#define lis_matrix_set_bsc_f F77_FUNC_(lis_matrix_set_bsc_f_, LIS_MATRIX_SET_BSC_F)
#define lis_matrix_set_coo_f F77_FUNC_(lis_matrix_set_coo_f_, LIS_MATRIX_SET_COO_F)
#define lis_matrix_set_dns_f F77_FUNC_(lis_matrix_set_dns_f_, LIS_MATRIX_SET_DNS_F)
#define lis_matrix_set_vbr_f F77_FUNC_(lis_matrix_set_vbr_f_, LIS_MATRIX_SET_VBR_F)
#define lis_matrix_assemble_f F77_FUNC_(lis_matrix_assemble_f_, LIS_MATRIX_ASSEMBLE_F) 
#define lis_matrix_is_assembled_f F77_FUNC_(lis_matrix_is_assembled_f_, LIS_MATRIX_IS_ASSEMBLED_F) 
#define lis_matrix_malloc_f F77_FUNC_(lis_matrix_malloc_f_, LIS_MATRIX_MALLOC_F)
#define lis_matrix_malloc_csr_f F77_FUNC_(lis_matrix_malloc_csr_f_, LIS_MATRIX_MALLOC_CSR_F)
#define lis_matrix_malloc_csc_f F77_FUNC_(lis_matrix_malloc_csc_f_, LIS_MATRIX_MALLOC_CSC_F)
#define lis_matrix_malloc_bsr_f F77_FUNC_(lis_matrix_malloc_bsr_f_, LIS_MATRIX_MALLOC_BSR_F)
#define lis_matrix_malloc_msr_f F77_FUNC_(lis_matrix_malloc_msr_f_, LIS_MATRIX_MALLOC_MSR_F)
#define lis_matrix_malloc_ell_f F77_FUNC_(lis_matrix_malloc_ell_f_, LIS_MATRIX_MALLOC_ELL_F)
#define lis_matrix_malloc_jad_f F77_FUNC_(lis_matrix_malloc_jad_f_, LIS_MATRIX_MALLOC_JAD_F)
#define lis_matrix_malloc_dia_f F77_FUNC_(lis_matrix_malloc_dia_f_, LIS_MATRIX_MALLOC_DIA_F)
#define lis_matrix_malloc_bsc_f F77_FUNC_(lis_matrix_malloc_bsc_f_, LIS_MATRIX_MALLOC_BSC_F)
#define lis_matrix_malloc_vbr_f F77_FUNC_(lis_matrix_malloc_vbr_f_, LIS_MATRIX_MALLOC_VBR_F)
#define lis_matrix_malloc_coo_f F77_FUNC_(lis_matrix_malloc_coo_f_, LIS_MATRIX_MALLOC_COO_F)
#define lis_matrix_malloc_dns_f F77_FUNC_(lis_matrix_malloc_dns_f_, LIS_MATRIX_MALLOC_DNS_F)
#define lis_matrix_convert_f F77_FUNC_(lis_matrix_convert_f_, LIS_MATRIX_CONVERT_F)
#define lis_matrix_copy_f F77_FUNC_(lis_matrix_copy_f_, LIS_MATRIX_COPY_F)
#define lis_matrix_scaling_f F77_FUNC_(lis_matrix_scaling_f_, LIS_MATRIX_SCALING_F)
#define lis_matrix_get_diagonal_f F77_FUNC_(lis_matrix_get_diagonal_f_, LIS_MATRIX_GET_DIAGONAL_F)
#define lis_matrix_set_blocksize_f F77_FUNC_(lis_matrix_set_blocksize_f_, LIS_MATRIX_SET_BLOCKSIZE_F)


/**************/
/* VECTOR     */
/**************/
#define lis_vector_create_f F77_FUNC_(lis_vector_create_f_, LIS_VECTOR_CREATE_F) 
#define lis_vector_duplicate_f F77_FUNC_(lis_vector_duplicate_f_, LIS_VECTOR_DUPLICATE_F) 
#define lis_vector_destroy_f F77_FUNC_(lis_vector_destroy_f_, LIS_VECTOR_DESTROY_F) 
#define lis_vector_set_size_f F77_FUNC_(lis_vector_set_size_f_, LIS_VECTOR_SET_SIZE_F) 
#define lis_vector_get_size_f F77_FUNC_(lis_vector_get_size_f_, LIS_VECTOR_GET_SIZE_F) 
#define lis_vector_get_range_f F77_FUNC_(lis_vector_get_range_f_, LIS_VECTOR_GET_RANGE_F) 
#define lis_vector_set_value_f F77_FUNC_(lis_vector_set_value_f_, LIS_VECTOR_SET_VALUE_F) 
#define lis_vector_set_values_f F77_FUNC_(lis_vector_set_values_f_, LIS_VECTOR_SET_VALUES_F) 
#define lis_vector_set_values2_f F77_FUNC_(lis_vector_set_values2_f_, LIS_VECTOR_SET_VALUES2_F) 
#define lis_vector_get_value_f F77_FUNC_(lis_vector_get_value_f_, LIS_VECTOR_GET_VALUE_F) 
#define lis_vector_get_values_f F77_FUNC_(lis_vector_get_values_f_, LIS_VECTOR_GET_VALUES_F) 
#define lis_vector_scatter_f F77_FUNC_(lis_vector_scatter_f_, LIS_VECTOR_SCATTER_F) 
#define lis_vector_gather_f F77_FUNC_(lis_vector_gather_f_, LIS_VECTOR_GATHER_F) 
#define lis_vector_print_f F77_FUNC_(lis_vector_print_f_, LIS_VECTOR_PRINT_F) 
#define lis_vector_set_all_f F77_FUNC_(lis_vector_set_all_f_, LIS_VECTOR_SET_ALL_F) 
#define lis_vector_axpy_f F77_FUNC_(lis_vector_axpy_f_, LIS_VECTOR_AXPY_F) 
#define lis_vector_xpay_f F77_FUNC_(lis_vector_xpay_f_, LIS_VECTOR_XPAY_F) 
#define lis_vector_axpyz_f F77_FUNC_(lis_vector_axpyz_f_, LIS_VECTOR_AXPYZ_F) 
#define lis_vector_copy_f F77_FUNC_(lis_vector_copy_f_, LIS_VECTOR_COPY_F) 
#define lis_vector_scale_f F77_FUNC_(lis_vector_scale_f_, LIS_VECTOR_SCALE_F) 
#define lis_vector_pmul_f F77_FUNC_(lis_vector_pmul_f_, LIS_VECTOR_PMUL_F) 
#define lis_vector_pdiv_f F77_FUNC_(lis_vector_pdiv_f_, LIS_VECTOR_PDIV_F) 
#define lis_vector_abs_f F77_FUNC_(lis_vector_abs_f_, LIS_VECTOR_ABS_F) 
#define lis_vector_reciprocal_f F77_FUNC_(lis_vector_reciprocal_f_, LIS_VECTOR_RECIPROCAL_F) 
#define lis_vector_shift_f F77_FUNC_(lis_vector_shift_f_, LIS_VECTOR_SHIFT_F) 
#define lis_vector_dot_f F77_FUNC_(lis_vector_dot_f_, LIS_VECTOR_DOT_F) 
#define lis_vector_nrm1_f F77_FUNC_(lis_vector_nrm1_f_, LIS_VECTOR_NRM1_F) 
#define lis_vector_nrm2_f F77_FUNC_(lis_vector_nrm2_f_, LIS_VECTOR_NRM2_F) 
#define lis_vector_nrmi_f F77_FUNC_(lis_vector_nrmi_f_, LIS_VECTOR_NRMI_F) 
#define lis_vector_sum_f F77_FUNC_(lis_vector_sum_f_, LIS_VECTOR_SUM_F) 
#define lis_vector_is_null_f F77_FUNC_(lis_vector_is_null_f_, LIS_VECTOR_IS_NULL_F) 
/**************/
/* SOLVER     */
/**************/
#define lis_solver_create_f F77_FUNC_(lis_solver_create_f_, LIS_SOLVER_CREATE_F) 
#define lis_solver_destroy_f F77_FUNC_(lis_solver_destroy_f_, LIS_SOLVER_DESTROY_F) 
#define lis_solve_f F77_FUNC_(lis_solve_f_, LIS_SOLVE_F) 
#define lis_solver_set_option_f F77_FUNC_(lis_solver_set_option_f_, LIS_SOLVER_SET_OPTION_F) 
#define lis_solver_get_iters_f F77_FUNC_(lis_solver_get_iters_f_, LIS_SOLVER_GET_ITERS_F) 
#define lis_solver_get_itersex_f F77_FUNC_(lis_solver_get_itersex_f_, LIS_SOLVER_GET_ITERSEX_F) 
#define lis_solver_get_time_f F77_FUNC_(lis_solver_get_time_f_, LIS_SOLVER_GET_TIME_F) 
#define lis_solver_get_timeex_f F77_FUNC_(lis_solver_get_timeex_f_, LIS_SOLVER_GET_TIMEEX_F) 
#define lis_solver_get_residualnorm_f F77_FUNC_(lis_solver_get_residualnorm_f_, LIS_SOLVER_GET_RESIDUALNORM_F) 
#define lis_solver_get_rhistory_f F77_FUNC_(lis_solver_get_rhistory_f_, LIS_SOLVER_GET_RHISTORY_F) 
#define lis_solver_get_solver_f F77_FUNC_(lis_solver_get_solver_f_, LIS_SOLVER_GET_SOLVER_F) 
#define lis_solver_get_precon_f F77_FUNC_(lis_solver_get_precon_f_, LIS_SOLVER_GET_PRECON_F) 
#define lis_solver_get_solvername_f F77_FUNC_(lis_solver_get_solvername_f_, LIS_SOLVER_GET_SOLVERNAME_F) 
#define lis_solver_get_preconname_f F77_FUNC_(lis_solver_get_preconname_f_, LIS_SOLVER_GET_PRECONNAME_F) 
#define lis_solver_set_optionC_f F77_FUNC_(lis_solver_set_optionc_f_, LIS_SOLVER_SET_OPTIONC_F) 
/**************/
/* ESOLVER     */
/**************/
#define lis_esolver_create_f F77_FUNC_(lis_esolver_create_f_, LIS_ESOLVER_CREATE_F) 
#define lis_esolver_destroy_f F77_FUNC_(lis_esolver_destroy_f_, LIS_ESOLVER_DESTROY_F) 
#define lis_esolve_f F77_FUNC_(lis_esolve_f_, LIS_ESOLVE_F) 
#define lis_esolver_set_option_f F77_FUNC_(lis_esolver_set_option_f_, LIS_ESOLVER_SET_OPTION_F) 
#define lis_esolver_get_iters_f F77_FUNC_(lis_esolver_get_iters_f_, LIS_ESOLVER_GET_ITERS_F) 
#define lis_esolver_get_itersex_f F77_FUNC_(lis_esolver_get_itersex_f_, LIS_ESOLVER_GET_ITERSEX_F) 
#define lis_esolver_get_time_f F77_FUNC_(lis_esolver_get_time_f_, LIS_ESOLVER_GET_TIME_F) 
#define lis_esolver_get_timeex_f F77_FUNC_(lis_esolver_get_timeex_f_, LIS_ESOLVER_GET_TIMEEX_F) 
#define lis_esolver_get_evalues_f F77_FUNC_(lis_esolver_get_evalues_f_, LIS_ESOLVER_GET_EVALUES_F)
#define lis_esolver_get_evectors_f F77_FUNC_(lis_esolver_get_evectors_f_, LIS_ESOLVER_GET_EVECTORS_F) 
#define lis_esolver_get_residualnorm_f F77_FUNC_(lis_esolver_get_residualnorm_f_, LIS_ESOLVER_GET_RESIDUALNORM_F) 
#define lis_esolver_get_rhistory_f F77_FUNC_(lis_esolver_get_rhistory_f_, LIS_ESOLVER_GET_RHISTORY_F) 
#define lis_esolver_get_esolver_f F77_FUNC_(lis_esolver_get_esolver_f_, LIS_ESOLVER_GET_ESOLVER_F) 
#define lis_esolver_get_esolvername_f F77_FUNC_(lis_esolver_get_esolvername_f_, LIS_ESOLVER_GET_ESOLVERNAME_F) 
#define lis_esolver_set_optionC_f F77_FUNC_(lis_esolver_set_optionc_f_, LIS_ESOLVER_SET_OPTIONC_F) 
/**************/
/* MATVEC     */
/**************/
#define lis_matvec_f F77_FUNC_(lis_matvec_f_, LIS_MATVEC_F) 
#define lis_matvect_f F77_FUNC_(lis_matvect_f_, LIS_MATVECT_F) 
/**************/
/* SYSTEM     */
/**************/
#define lis_set_comm_world_f F77_FUNC_(lis_set_comm_world_f_, LIS_SET_COMM_WORLD_F)
#define lis_finitialize_f F77_FUNC_(lis_finitialize_f_, LIS_FINITIALIZE_F) 
#define lis_finalize_f F77_FUNC_(lis_finalize_f_, LIS_FINALIZE_F) 
#define lis_wtime_f F77_FUNC_(lis_wtime_f , LIS_WTIME_F)
#define CHKERR_f F77_FUNC_(chkerr_f_, CHKERR_F) 
#define lis_set_argv_begin_f F77_FUNC_(lis_set_argv_begin_f_, LIS_SET_ARGV_BEGIN_F) 
#define lis_set_argv_f F77_FUNC_(lis_set_argv_f_, LIS_SET_ARGV_F) 
#define lis_set_argv_end_f F77_FUNC_(lis_set_argv_end_f_, LIS_SET_ARGV_END_F) 
#define lis_arg2args_f F77_FUNC_(lis_arg2args_f_, LIS_ARG2ARGS_F) 
#define lis_input_f F77_FUNC_(lis_input_f_, LIS_INPUT_F)
#define lis_input_matrix_f F77_FUNC_(lis_input_matrix_f_, LIS_INPUT_MATRIX_F)
#define lis_input_vector_f F77_FUNC_(lis_input_vector_f_, LIS_INPUT_VECTOR_F)
#define lis_output_f F77_FUNC_(lis_output_f_, LIS_OUTPUT_F) 
#define lis_output_matrix_f F77_FUNC_(lis_output_matrix_f_, LIS_OUTPUT_MATRIX_F) 
#define lis_output_vector_f F77_FUNC_(lis_output_vector_f_, LIS_OUTPUT_VECTOR_F) 
#define lis_solver_output_rhistory_f F77_FUNC_(lis_solver_output_rhistory_f_, LIS_SOLVER_OUTPUT_RHISTORY_F) 
#define lis_esolver_output_rhistory_f F77_FUNC_(lis_esolver_output_rhistory_f_, LIS_ESOLVER_OUTPUT_RHISTORY_F) 

subprocessでシェルコマンドの出力をリアルタイムに取得する

久々のメモです。

Pythonでsubprocessを用いてコマンドを実行した際の標準出力を、リアルタイムで取得してきて表示するサンプルプログラムです。良く見られるサンプルプログラムだと、きちんとコマンドが終了してからの出力を変数に取得する方法しか載ってなかったりしますが、以下のページから情報を得ることができました。

http://stackoverflow.com/questions/1606795/catching-stdout-in-realtime-from-subprocess

以下のような使い方をします。

#/usr/bin/python
# -*- codint: utf-8 -*-

import subprocess, time, os, sys
cmd = [sys.executable, 'test_out.py']

p = subprocess.Popen(cmd,
  stdout=subprocess.PIPE,
  stderr=subprocess.STDOUT)

#for line in p.stdout:
#    print line,
for line in iter(p.stdout.readline, b''):
  print(line.rstrip() + " world !!")

引数cmdにわたっている配列を実行します。
この場合は、test_out.pyというスクリプトを実行していますが、以下のような内容になっています。

#/usr/bin/python
# -*- codint: utf-8 -*-

import sys
import time

for i in range(10):
  print ("%d Hello" % (i))
  sys.stdout.flush()
  time.sleep(1)

単に"Hello"を一秒ごとに出力するサンプルです。

これを実行すると、一秒ごとに吐き出された出力をリアルタイムに取得し、編集して出力することができます。

$ python main_out.py 
0 Hello world !!
1 Hello world !!
2 Hello world !!
3 Hello world !!
4 Hello world !!
5 Hello world !!
6 Hello world !!
7 Hello world !!
8 Hello world !!
9 Hello world !!

特定のプロセスの情報を見る

Linuxで使用メモリを知りたい時などはpsコマンドを良く使います。普段はその出力をgrepで抜き出していたのですが、それをもっと便利に使いたいということで、psgrepというコマンドで簡単に特定のコマンドをチェックできるようにしました。

psgrep

#!/bin/bash
if [ $# -eq 0 ]; then
  echo "psgrep [process name]"
  exit
fi
ps aux | head -1 
ps aux | grep $1

これをbinの中に入れて実行権限を与えればOK

使い方

psgrep プロセス名