IBV_POST_SEND(3)

作成日:2014.05.12

NAME

ibv_post_send - Send Queue (SQ) に work request (WR) のリストを登録する。

SYNOPSIS

#include <infiniband/verbs.h>

int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,
                  struct ibv_send_wr **bad_wr);

DESCRIPTION

ibv_post_send() は queue pair qp の send queue (RQ) に対して、wr から片方向リンクでつながっている一連の Send Work Request (WR) のリストを登録する。 もしリストの先頭から WR を登録し、最初に失敗した箇所で停止し、bad_wr に登録に失敗した WR の struct ibv_send_wr 構造体へのポインタをコピーする。 例えば、最初の Send WR の登録に失敗した場合、*bad_wr = wr がコピーされる。

Table 1: struct ibv_send_wr 構造体
メンバ名説明
wr_iduint64_tユーザーが自由に設定できる WR ID。この値は ibv_poll_cq で取り出す完了の中に埋め込まれる。
nextstruct ibv_send_wr *1 度の ibv_post_send() で複数の Send WR を登録したい場合、next を使って片方向リストを作る。最後の Send WR には NULL を設定する。
sg_liststruct ibv_sge *ローカルバッファを示す scatter/gather 組を struct ibv_sge 構造体の配列へのポインタで指定する。num_sge が 0 なら NULL でよい。
num_sgeintsg_list が指す struct ibv_sge 構造体の配列の要素数。0 以上で QP ケーパビリティの max_recv_sge 未満の値を指定すること。0 はローカルバッファのサイズが 0 を意味する。
opcodeenum ibv_wr_opcoe オペレーション種類を指定する。 QP のサービスタイプによって指定可能なオペレーションは制限される。
オペレーション名 マクロ IBV_QPT_UD IBV_QPT_UC IBV_QPT_RC
SENDIBV_WR_SEND SupportedSupportedSupported
SEND with ImmediateIBV_WR_SEND_WITH_IMM SupportedSupportedSupported
RDMA WRIEIBV_WR_RDMA_WRITE  SupportedSupported
RDMA WRITE with ImmediateIBV_WR_RDMA_WRITE_WITH_IMM  SupportedSupported
RDMA READIBV_WR_RDMA_READ   Supported
Compare and SwapIBV_WR_ATOMIC_CMP_AND_SWP   Supported
Fetch and AddIBV_WR_ATOMIC_FETCH_AND_ADD   Supported

詳細は「InfiniBand プログラムに必要な基本的な概念」 7.オペレーションの種類を参考。
send_flagsint Send WR のプロパティを設定する。以下のマクロの論理和を指定する。
IBV_SEND_FENCE
このフラグを立てた Send WR が実行される前に、先行する全ての Send WQE が完了するのを待つ。
このフラグは Send WR の実行順序保証のために使用される。 InfiniBand の仕様上、SEND(with Immediate も含む)と RDMA WRITE(with Immediate も含む)は SQ に登録した順に実行されることが保証されているが、RDMA READ と Atomic Operations は SQ の登録順と実行順は逆転する可能性がある。しかしこのフラグを使うと RDMA READ と Atomic Operations も含めた実行順序保証が可能になる。 ただし先行する Send WR の完了を待つので、性能は低下する。
詳細は InfiniBand Architecture Specification Volume 1 Release 1.2.1 10.8.3 WORK REQUEST PROCESSING も参照のこと。
IBV_SEND_SIGNALED
このフラグを立てた Send WR は、処理が成功した場合でも完了が生成され CQ に投入される。
  • qpibv_create_qp()sq_sig_all に 1 を立てて生成された QP の場合、IBV_SEND_SIGNALED フラグをつけなくても完了が生成される。
  • qpibv_create_qp()sq_sig_all に 0 を立てて生成された QP の場合、IBV_SEND_SIGNALED フラグをつけない場合は完了が生成されない。IBV_SEND_SIGNALED フラグをつけた場合は完了が生成される。
Send WR がエラーの場合は、このフラグの有無とは無条件に CQ に完了エラーが投入される。
IBV_SEND_SOLICITED
このフラグを立てた Send WR は、パケット内に SOLICITED ビットが立ち、受信側 QP では Solicited completion event が発生する。
プログラム的には、受信側で completion channel を使いかつ ibv_req_notify_cq() の引数 solicited_only を非 0 に設定して待ちうけるた場合、送信側からはこのフラグを立てて送った Send WR 以外では completion notification が発生が派生しない。
使い方としては、送信側から受信側への一連のメッセージを複数の Send WR に分割して送る必要がある場合、最後の Send WR だけに IBV_SEND_SOLICITED をつけることで、受信側に頻繁に割り込みがあがるのを防ぐことができる。
IBV_SEND_INLINE
このフラグを立てた Send WR は、ローカルバッファの内容をインラインデータとして Sned WQE 中に含めて登録する。 これは SEND オペレーション、SEND with Immediate オペレーション、RDMA WRITE オペレーション、RDMA WRITE with Immediate オペレーションでのみ有効である。
InfiniBand は「InfiniBand プログラムに必要な基本的な概念」 4. メモリモデル:ゼロコピーと RDMAで説明したように転送元データも HCA が DMA で転送する。 ただしローカルバッファのサイズが小さい場合は、DMA 転送するよりも Send WR と一緒にデータも送った方が効率的である。 この場合にインラインデータを使う。

インラインデータが有効なのは、ローカルバッファの合計サイズが QP に設定された max_inline_data 以下である必要がある。 max_inline_dataibv_create_qp() で設定しており、ibv_query_qp() で取得し確認できる。 ローカルバッファの合計サイズが max_inline_data を越えていた場合や対応してないオペレーションでは、IBV_SEND_INLINE を設定しなかったのと同様に振舞う。
インラインデータを使った場合、ローカルバッファの memory region の L_Key のチェックは行われない。
imm_datauint32_tImmediate data。SEND with Immediate オペレーションと RDMA WRITE with Immediate オペレーションで使用する。ネットワークバイトオーダーで指定。
wrwr は共用体で RC/UC サービスの SEND オペレーション以外で使用する。
rdmawr.rdma は RDMA WRITE オペレーション、RDMA WRITE with Immediate オペレーション、RDMA READ オペレーションを使用する際に指定する。
remote_addruint64_tリモートメモリバッファの開始アドレス。
rkeyuint32_tリモートの memory region の R_Key。
atomicwr.atomic は Compare and Swap オペレーションと Fetch and Add オペレーションを使用する際に指定する。
remote_addruint64_tリモートメモリバッファの開始アドレス。8 バイト境界に揃える必要がある。
compare_adduint64_tメモリ内容の比較に使う「現在値」。Compare and Swaop オペレーションでのみ指定。
swapuint64_t比較が成功した時にメモリ内容を書き換える「変更値」。Compare and Swaop オペレーションでのみ指定。
rkeyuint32_tメモリ内容に追加する「増分」。Fetch and Add オペレーションでのみ指定。
udwr.ud は UD サービスにおいて SEND オペレーションを使用する際に指定する。
ahstruct ibv_ah *送信先を示す address handle(AH)。ibv_create_ah() で作成したものを指定。
remote_qpnuint32_t送信先の QP 番号。
remote_qkeyuint32_t Q_Key となる 32 ビット値を設定する。
0x0000,0000〜0x7FFF,FFFF パケットの Q_Key フィールドは remote_qkey を埋め込む。
0x8000,0000〜0xFFFF,FFFF remote_qkey は無視され、パケットの Q_Key フィールドは QP に対して ibv_modify_qp() で設定した qkey の値を埋め込む。
(ただし mlx4 では 0xFFFF,0000〜0xFFFF,FFFF は HCA の予約されている)

詳細は「InfiniBand プログラムに必要な基本的な概念」 12.2 UD サービスのための保護機構を参照のこと。

QP ケーパビリティは ibv_create_qp()ibv_modify_qp() で設定可能で、ibv_query_qp() で現在値を取得できる。

1 つの Sen WR のローカルバッファは複数の scatter/gather 組で構成できるが、各 scatter/gather は同一の memory region 内に収まる必要がある。 「InfiniBand プログラムに必要な基本的な概念」 6.5 Work Request と Work Completion のデータ構造を参照のこと。

Table 2: struct ibv_sge 構造体
メンバ名説明
addruint64_t1 s/g 組の開始アドレス。
lengthuint32_t1 s/g 組の長さ。
lkeyuint32_taddrlength が所属する memory region の L_Key を指定する。ibv_reg_mr() の戻り値となった struct ibv_mr 構造体の lkey の値をコピーすればよい。

Send WR で指定するローカルバッファのサイズは scatter/gather 配列の合計である。 UD QP では、この合計サイズがポートの Active MTU を越えた場合はエラーとなる(ポートの Active MTU は ibv_query_port() によって取得できる active_mtu で確認できる)。 同様に RC/UC QP では、この合計サイズが HCA のメッセージの最大長を越えた場合はエラーとなる(メッセージの最大長は ibv_query_port() によって取得できる max_msg_sz で確認できる)。 詳細は 「InfiniBand のエラーハンドリングのモデルを理解する」 2.2 Local Length Error (IBV_LOC_LEN_ERR)を参照のこと。

Send WR で指定するローカルバッファのサイズを 0 にしたい場合は、struct ibv_recv_wr 構造体の num_sge の値を 0 に設定すること。 struct ibv_sge 構造体の length に 0 を指定した場合、HCA によっては 0x8000,0000 バイトを指定したとみなされる。

Send WR はローカルバッファをどのように使用するかは、Table 3 に従うこと。

Table 3: オペレーションごとのデータの方向
オペレーション 転送の方向 ローカルバッファ リモートバッファ 転送サイズ
SEND オペレーション(with Immediate も含む) ローカルバッファのデータをリモートへ 必要なアクセス権限は 0(なし) Receive WR を使用。Receive WR に必要なアクセス権限は IBV_ACCESS_LOCAL_WRITE ローカルバッファの合計サイズ
RDMA WRITE wih Immediate オペレーション
  • wr.rdma.rkey が示す memory region に IBV_ACCESS_LOCAL_WRITEIBV_ACCESS_REMOTE_WRITE が必要。
  • Immeidate Data を受け取るのに Receive WR を使用。Receive WR に必要なアクセス権限は 0 なし。
RDMA WRITE オペレーション wr.rdma.rkey が示す memory region に IBV_ACCESS_LOCAL_WRITEIBV_ACCESS_REMOTE_WRITE が必要。
READ オペレーション リモートからのデータをローカルバッファへ IBV_ACCESS_LOCAL_WRITE wr.rdma.rkey が示す memory region に IBV_ACCESS_REMOTE_READ が必要。
Compare and Swap オペレーション
Fetch and Add オペレーション
wr.rdma.rkey が示す memory region に IBV_ACCESS_LOCAL_WRITEIBV_ACCESS_REMOTE_ATOMIC が必要。 8 バイト固定

RETURN VALUE

ibv_post_recv() は成功した場合、0 を返す。 失敗した場合は、エラーの原因を示す値(errno と同じ)を返す。

ERRORS

ibv_post_send() はエラー時には復帰値に errno と同じ値が入る。

ENOMEMQP ケーパビリティの max_send_wr を越えて Send WR を登録しようとした。

InfiniBand Architecture Specification Volume 1 Release 1.2.1 C10-96 には、QP が Reset、Init、RTR ステートの時に Send WR を SQ に登録する場合、immediate error を返す仕様になっている。 つまり ibv_post_send() は非 0 値を返す必要がある。 しかし一部の HCA では、Reset、Init、RTR ステートでも ibv_post_send() を実行しても成功を返す場合がある。 この場合、その後 QP を RTS ステートまで遷移させた時に正しく送信できることは保証されないと思われる。

NOTES

SEE ALSO

InfiniBand Verbs API Referenceibv_create_qp(3)ibv_create_ah(3)ibv_post_recv(3)ibv_post_src_recv(3)ibv_post_cq(3)

AUTHORS

原文 Dotan Barak <dotanba@gmail.com>
原文にない加筆がある。

コメント

コメントを書き込む

TOP    掲示板    戻る
Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp