徒然なるままに

個人の備忘録を中心としたブログです

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
自分がはまった点をメモ

・ソースを落としてきてビルド、インストールでは、依存関係にあるモジュール等が入っていない可能性があるので簡単に済ませるならportを使う。

・インクルードパス等がちゃんと/opt/local/include, /opt/local/libなど(boostをインストールした場所)に通っているか(これはMacPortsのインストール後にちゃんと設定すべきかも)

export LIBRARY_PATH=$LIBRARY_PATH:/opt/local/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/local/lib
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/opt/local/include
export DYLD_LIBRARY_PATH=/opt/local/lib


CPLUS_INCLUDE_PATHが通ってないとヘッダファイルが無いと言われる。
DYLD_LIBRARY_PATHが通ってないと実行時に動的リンクに失敗する.

・コンパイル時に-lboost_system-mtをつける
 
g++ test.cpp -lboost_system-mt


スポンサーサイト
MPIの実装でメジャーなものがopenMPIとmpich。
以前のmpichはプロセスデーモンと呼ばれるデーモンを予め起動しておく必要があったが
それがいらなくなり、十分に安定しているとうことでmpichを使ってみることにした。
こういうのは実際に使ってみないと分からない。

mpichは現在mpich2になっているらしいのでmpich2をインストール。
http://www.mpich.org/downloads/から、最新のstable版をインストール

$wget http://www.mpich.org/static/downloads/3.1.1/mpich-3.1.1.tar.gz
$tar xzvf mpich-3.1.1.tar.gz
$cd mpich-3.1.1
$./configure --prefix=/usr/local 2>&1 | tee c.txt
$make -j 8 | tee m.txt
$make install 2>&1 | tee mi.txt


でインストールは完了。


続いて、並列実行の基本

mpiexec -n プロセス数 a.out
現在のノード内で指定したプロセス数a.outを立ち上げる。

mpiexec -f machinefile -n プロセス数 a.out
machinefileに記述したhostに、指定したプロセス数を振り分けて立ち上げる。

a.outは別にmpiプログラムでなくても普通のコマンドで良い。
試す分にはhostnameなんかを使うと分かりやすくていい。

machinefileには一行毎に"ホスト名:プロセッサ数"を記述。
こんな感じで記述
machinefile
host01:1
host02:2
host03:4
host04:4


ホスト名は/etc/hostsにちゃんと記述してあるものを使ってください
machinefileに直接、マシンのIPアドレスを記述しても構いません。
これらのhostにはパスフレーズなしの公開鍵でsshログインできるようになっていることが条件です。

実行結果
@host02$ mpiexec -n 2 hostname
host02.example.com
host02.example.com
@host02$ mpiexec -f machinefile -n 4 hostname
host01.example.com
host02.example.com
host02.example.com
host03.example.com



続いてmpiプログラムのコンパイル方法について

mpiccコマンドでCで書かれたmpiプログラムのコンパイル
mpic++コマンドでC++で書かれたmpiプログラムのコンパイル


MPIプログラミングについては、いろんな所で解説されていますので、
ここでは詳しい解説はしません。
一応リンクだけ紹介しておくと、HPさんのドキュメントで結構古いんですけど、
MPIプログラミングの基本的な考え方が初学者でもしっかり学べるのでおすすめです。
実際関数の使い方なんかもほとんど変わっていませんしね。
http://h50146.www5.hp.com/solutions/hpc/stc/soft/pdfs/mpi_training.pdf


てことで実際のプログラム
hello.c
#include "mpi.h"
#include

int main(int argc, char **argv)
{
int n, myid, numprocs, i;
int name_len;
char processor_name[MPI_MAX_PROCESSOR_NAME];

MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Get_processor_name(processor_name, &name_len);
printf("Hello World %d/%d on %s\n",myid,numprocs,processor_name);
MPI_Finalize();
}


実行結果
@host02$ mpicc hello.c 
@host02$ mpiexec -n 4 ./a.out
Hello World 0/4 on host01.example.com
Hello World 1/4 on host02.example.com
Hello World 3/4 on host03.example.com
Hello World 2/4 on host02.example.com


後は公式のmpich2からAPIのドキュメントを読んで
MPIプログラミングするだけです。

以上導入でした。
多重I/O(I/O Multiplexing)について勉強する機会があったのでメモ。

具体的な使用方法の前に多重I/Oについての前置き。

多重I/Oとは、複数のプロセスにread(recv)要求を行っている状況において
順番を気にせず、読み込みが完了したプロセスから順次読み込んだデータを使って処理する場合に使う。

いわゆるイベント駆動型動作であり、一つでも読み込みが完了していれば
まだ読み込みが終了していないプロセスのread待ちによるブロックがない。

例えば100プロセスとの通信で、ファイルディスクリプタを100個所持している状況を考えよう。
1つのプロセスからの入力を待って、入力が来たら、次のプロセスからの入力を待って、・・・として
全てのプロセスからデータを読み込むのは非常に非効率である。

そこで100個のファイルディスクリプタを監視して、
読み込みイベントがあったファイルディスクリプタから先に処理ができるようにしたものが
多重I/Oである。


多重I/Oを実現する手段として、Linuxにselecet(2),poll(2),epoll(2)がある。

selectは扱えるファイルディスクリプタ数に上限があるので、selectを使うならpollを使った方がよい(マシ)。
pollは扱えるファイルディスクリプタ数を無限にできる。
しかし、select,pollはファイルディスクリプタを一つずつループで見ていく方法で
ファイルディスクリプタを監視するのでO(n)の時間がかかる。

一方、epollはファイルディスクリプタの数が無制限なのに加え、ディスクリプタの状態をkernelで管理するため
ファイルディスクリプタの状態が変わったものに対して直接通知ができる。

つまり性能としては select<poll<epoll である。

epollはnginx(エンジンエックス)というサーバーやプロキシに使われるソフトウェアで使われている。
参考サイト:入門! nginx - 馬鹿と天才は紙一重



やっと本題のepollの使い方に入ります・・・。

まずはepoll_create(2)で、epollのインスタンスを作成します。
FD_SIZEは監視するファイルディスクリプタ数の上限であり、
この値をepoll_create(2)に渡しているが、これは後方互換性のものであり、
現在はこの上限を越えるファイルディスクリプタを追加すると、カーネルが自動的にメモリの追加割り当てを行うので
この上限は形骸化している。ただし、現在でも0より大きな値を渡さなければいけない。

#define FD_SIZE 100
int epfd;
epfd = epoll_create(FD_SIZE)



int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll_create(2)でディスクリプタのインタフェースを操作する。
このシステムコールは、ファイルディスクリプタ epfd が参照する epoll インスタンスに対する操作を行う。 対象のファイルディスクリプタ fd に対して、 操作 op の実行が要求される。

opで指定する値の一つでよく使うのは「EPOLL_CTL_ADD」。
対象のファイルディスクリプタ fd をファイルディスクリプタ epfd が参照する epoll インスタンスに登録し、イベント event を fd に結び付けられた内部ファイルに関連付ける。

int conn_sock; //プロセス間の通信に使うファイルディスクリプタ(以降既に通信ができているものとする)
struct epoll_event ev; // epoll_event

memset(&ev, 0, sizeof ev); // epoll_eventの初期化
ev.events = EPOLLIN; // 入力を待つ
ev.data.fd = conn_sock;
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_sock, &ev); //epollインスタンスにfdを追加し、イベントをfdに関連付ける。



int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
epoll_wait() システムコールは、ファイルディスクリプタ epfd で参照される epoll インスタンスに対するイベントを待つ。 events が指すメモリ領域には、 呼び出し側が利用可能なイベントが格納される。最大 maxevents 個のイベントが epoll_wait() によって返される。 maxevents 引き数は 0 より大きくなければならない。

timeout 引き数は、 epoll_wait() が停止する最小時間をミリ秒で指定する。 timeout を -1 に指定すると、epoll_wait() は無限に停止する。timeoutを 0 に指定すると、 epoll_wait() は利用可能なイベントがなくても、すぐに返る。

成功した場合、 epoll_wait() は要求された I/O に対して準備ができているファイルディスクリプタの数を返す。 また要求された timeout ミリ秒の間にファイルディスクリプタが準備できない場合は、0 を返す。 エラーが起こった場合、 epoll_wait() は -1 を返し、 errno を適切に設定する。

epoll_events events[FD_SIZE];

while (1) {
int i;
int nfd = epoll_wait(epfd, events, MAX_EVENTS, -1); // epoll_waitは準備ができているファイルディスクリプタの数を返す

for (i = 0; i < nfd; i++) {
if (events[i].data.fd == conn_sock) { // 目的のfdが含まれていたらそのfd専用の操作を行う。
int n = read(conn_sock,&data,sizeof(data));
if(n<0){ perror("read"); exit(1); }
}
}
}


↓のサイトでepollを使った良いテストコードが紹介されています。
epoll を使った echo サーバ
・CKEditor
テキストボックスを高性能にする。

・Security Review
セキュリティチェックができる。

Views, Rules, Panels, Chaos tool suite
drupal7のインストール時に何ヶ所かERRORが出たので、対策方法を記載しておきます。


・使用データベースでMySQLが選択できない
PDO_MYSQLが有効になっていない可能性が高いです。
phpinfo()で、pdo_mysqlの項目があるか確認しましょう。
なかったらpdo_mysqlをインストールする必要があります。
方法は、pdo_mysqlモジュールのソースをコンパイルして.soファイルを読み込むようにします。
ソースコードを落としてきて、コンパイル、インストールする必要があるのですが
peclというPHPで利用できる拡張ライブラリ(パッケージ)を提供しているサービスを使えば自動化されます。
pecl install pdo_mysql


ここで自分はPHPをローカルにインストールしていたせいで、ヘッダファイルのパスが通っておらず失敗した。
そこでソースコードを一度落としてきて手直し。
pecl download pdo_mysql
tar xzvf PDO_MYSQL-1.0.2.tgz
cd PDO_MYSQL-1.0.2/
phpize
./configure --with-pdo-mysql=/usr/local/mysql
make


ここでエラーが出るはず。どこのファイルの何行目でxxxx.hがnot existと言われていたら適切なパスを指定してやりましょう。
シンボリックリンクを作ってパスを通すやり方もあるそうなのですが、うまく行かなかったので
phpのインストール時に使用したソースファイルから
/usr/local/src/php-5.4.13/extから該当ヘッダーファイルを探して、直接指定しました。
5箇所くらい変更すればmakeが通りました。
sudo make install
#pdo_mysql.soができていることを確認
ls modules/pdo_mysql.so
#phpの拡張モジュールの動的ライブラリ置き場にコピー
sudo cp modules/pdo_mysql.so /usr/local/lib/php/ext
sudo apachectl restart



・クリーンURLが設定できない
Apacheのmod_rewriteモジュールがインストールされてない or httpd.confに適切な設定がされていない

mod_rewriteは有効でしたが、httpd.confに必要な記述が抜けていました。
htdocsのdrupalディレクトリにdrupalをインストールしている場合は以下の内容をhttpd.confに追加します。
<Directory /usr/local/htdocs/drupal>
RewriteEngine on
RewriteBase /drupal
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</Directory>


sudo apachectl restart

kamiyasu

Author:kamiyasu

QR

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。