このトピックでは、C または C++ を使用してカスタムプロセッサを開発する方法について説明します。
クイックスタートデモ
pai-prediction-example プロジェクトをダウンロードします。このプロジェクトには、次の 2 つのカスタムプロセッサが含まれています。
echo: リクエストを受信すると、このプロセッサは変更なしのユーザー入力とモデル内のファイルのリストを返します。
image_classification: このプロセッサは、MNIST 分類に使用されます。 JPG 形式の MNIST イメージが入力されると、イメージカテゴリが返されます。
コンパイルの詳細については、プロジェクトの README ファイルを参照してください。各プロセッサのオンプレミスデバッグの詳細については、対応するディレクトリの README ファイルを参照してください。
インターフェース定義
C または C++ を使用してカスタムプロセッサを開発するには、initialize() 関数と process() 関数を定義する必要があります。 initialize() 関数は、サービスの初期化中にモデルを読み込むために使用されます。 Process() 関数は、クライアントリクエストを処理して結果を返すために使用されます。次のコードブロックは、2 つの関数の宣言の例を示しています。
void *initialize(const char *model_entry, const char *model_config, int *state)パラメーター | 型 | 説明 |
model_entry | 入力パラメーター | モデルパッケージのエントリファイル。このパラメーターは、サービスの作成時に JSON 構成ファイルの model_entry フィールドに対応します。 model_entry フィールドの詳細については、「JSON デプロイメントのパラメーター」をご参照ください。 randomforest.pmml などのファイル名、または ./model などのディレクトリを指定できます。 |
model_config | 入力パラメーター | モデルのカスタム構成情報。このパラメーターは、サービスの作成時に構成ファイルの model_config フィールドに対応します。 model_config フィールドの詳細については、「JSON デプロイメントのパラメーター」をご参照ください。 |
state | 出力パラメーター | モデルの読み込みステータス。値が 0 の場合、モデルは読み込まれます。それ以外の場合、モデルの読み込みは失敗します。 |
戻り値 | すべての型をサポートするモデルのメモリアドレス。モデルは model 変数で指定されます。 | |
int process(void *model_buf, const void *input_data, int input_size,void **output_data, int *output_size)パラメーター | 型 | 説明 |
model_buf | 入力パラメーター | initialize() 関数によって返されるモデルメモリアドレス。 |
input_data | 入力パラメーター | 入力するデータ。文字列または BINARY 型にすることができます。 |
input_size | 入力パラメーター | 入力するデータの長さ。 |
output_data | 出力パラメーター | プロセッサによって返されるデータ。ヒープメモリはデータに割り当てる必要があります。モデルは構成に従ってメモリを解放します。 |
output_size | 出力パラメーター | プロセッサによって返されるデータの長さ。 |
戻り値 | 0 または 200 が返された場合、リクエストは成功です。 HTTP エラーコードを返すことができます。未定義の HTTP ステータスコードが返された場合、自動的に http 400 エラー に変換されます。 | |
サンプルコード
次のサンプルコードでは、モデルデータは読み込まれません。予測サービスは、ユーザーリクエストをクライアントに返します。
テストコードを作成します。
// モデルデータのロードなし。ユーザーリクエストをクライアントに返す #include <stdio.h> #include <string.h> extern "C" { void *initialize(const char *model_entry, const char *model_config, int *state) { *state = 0; return NULL; } int process(void *model_buf, const void *input_data, int input_size, void **output_data, int *output_size) { if (input_size == 0) { const char *errmsg = "input data should not be empty"; // 入力データが空であってはならない *output_data = strdup(errmsg); *output_size = strlen(errmsg); return 400; } *output_data = strdup((char *)input_data); *output_size = input_size; return 200; } }次の Makefile に基づいて入力データを SO ファイルとしてコンパイルします。
CC=g++ CCFLAGS=-I./ -D_GNU_SOURCE -Wall -g -fPIC LDFLAGS= -shared -Wl,-rpath=./ OBJS=processor.o TARGET=libpredictor.so all: $(TARGET) $(TARGET): $(OBJS) $(CC) -o $(TARGET) $(OBJS) $(LDFLAGS) -L./ %.o: %.cc $(CC) $(CCFLAGS) -c $< -o $@ clean: rm -f $(TARGET) $(OBJS)EAS サービスをデプロイします。サービスデプロイメントに必要な JSON 構成ファイルのプロセッサ関連の構成パラメーターについては、次のサンプルコードを参照してください。 processor_entry は、プロセッサのメインファイル(SO ファイル)を示します。
{ "name": "test_echo", // 名前:テストエコー "model_path": "http://*****.oss-cn-shanghai.aliyuncs.com/****/saved_model.tar.gz", // モデルパス "processor_path": "oss://path/to/echo_processor_release.tar.gz", // プロセッサパス "processor_entry": "libpredictor.so", // プロセッサエントリ "processor_type": "cpp", // プロセッサタイプ "metadata": { "instance": 1 // インスタンス } }