Prolog
Movidius

MovidiusをPrologで

ArcSoft_画像186.PNG

はじめに

2018年になって私はMovidiusチップのことを知りました。自分でも岡谷先生のDeep Larningの本を読み、数式を追いかけて実装を試みました。しかし、大量の行列計算を高速にこなす必要があり、実用になるものを作ることは困難であることが身に染みました。そんな折、既にある技術を応用できないかと探していました。いろいろ探しているうちにインテルのMovidiusという1万円程度の安価なチップが2017年後半に販売開始されていたことを知りました。さっそく購入し、これを動作させることに取り組みました。

なぜPrologか

Movidiusのサンプルコードの大半はPythonのコードで提供されています。PythonにはTensolflowなどの主要なDeep learningのツールが集中しています。しかし、私はPrologに拘りました。画像認識だけでは知的な動作はできず、Prologの有する論理、推論、バックトラックによる試行錯誤と組み合わさって知的な行動をするものを開発できるのではないかと考えています。

そこで、自作のO-PrologのコンパイラのCラッパーの機能を利用してMovidiusのCで提供されているAPIを利用することとしました。この結果、Movidiusの機能をPrologから利用することができるようになります。(ver1.20以降から使えるようになる見込みです)

述語とその仕様

自分のための覚書のような文書です。今後、試行錯誤しながら仕様を変更するかもしれません。
APIのうち主要なものを次の述語として取り込みました。
device_create/0
device_close/0
device_destroy/o
device_open/o
device_get_option/2
第一引数にオプションを表す整数、第二引数に受け取る変数
device_set_option/2
第一引数にオプションを表す整数、第二引数にセットする値
global_get_option/2
第一引数にオプションを表す整数、第二引数に受け取る変数
global_set_option/2
第一引数にオプションを表す整数、第二引数にセットする値
fifo_allocate/0
fifo_create/1
グラフに与える文字列をアトムとして与える。
fifo_destroy/0
load_graph_file/1
ロードするグラフの名前の文字列をアトムとして与える。

graph_allocate/0
graph_create/0
graph_destroy/0
graph_queue_inference/0

Hello world

device_create, device_open,device_clode,device_destroy
のテストです。とりあえずここまではOK。

2018-07-22_12-25-42.png

参考リンク

Intel® Movidius™ Neural Compute SDK C API v2
https://movidius.github.io/ncsdk/ncapi/ncapi2/c_api/readme.html

コード

:- c_include('<mvnc.h>').
:- c_option('-lmvnc').
:- c_global('ncStatus_t retCode;').
:- c_global('struct ncDeviceHandle_t* deviceHandle;').
:- c_global('struct ncGraphHandle_t* graphHandle = NULL;').
:- c_global('struct ncFifoHandle_t* inFifoHandle = NULL;').
:- c_global('struct ncTensorDescriptor_t inTensorDesc;').
:- c_global('struct ncFifoHandle_t* outFifoHandle = NULL;').
:- c_global('struct ncTensorDescriptor_t outTensorDesc;').


:- c_global('int data;').
:- c_global('unsigned int dataLength = sizeof(int);').
:- c_global('unsigned int graphSizeInBytes = 0;').
:- c_global('void* graphInMemory = NULL;').



device_create :-
    c_lang('retCode = ncDeviceCreate(0, &deviceHandle);'),
        c_lang('if(retCode == NC_OK) '),
    c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
    c_lang('return(YES);'),
    c_lang('Jset_tp(save1);'),
    c_lang('Junbind(save2);'),
    c_lang('return(NO);').

device_close :-
    c_lang('retCode = ncDeviceClose(deviceHandle);'),
    c_lang('if(retCode != NC_OK) '),
    c_lang('return(NO);'),
    c_lang('else return(YES);').


device_destroy :-
    c_lang('retCode = ncDeviceDestroy(&deviceHandle);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),        
    c_lang('return(NO);').

device_open :-
    c_lang('retCode = ncDeviceOpen(deviceHandle);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').  


device_get_option(X,Y) :-
    integer(X),
    var(Y),
    c_lang('retCode = ncDeviceGetOption(deviceHandle, Jget_int(varX), &data, &dataLength);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').

device_set_option(X,Y) :-
    integer(X),
    integer(Y),
    c_lang('data = Jget_int(varY);'),
    c_lang('retCode = ncDeviceSetOption(deviceHandle, Jget_int(varX), &data, &dataLength);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').


global_get_option(X,Y) :-
    integer(X),
    var(Y),
        c_lang('retCode = ncGlobalGetOption(Jget_int(varX), &data, &dataLength);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').


global_set_option(X,Y) :-
        integer(X),
        var(Y),
        c_lang('retCode = ncGlobalSetOption(Jget_int(varX), &data, &dataLength);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').


/*--------FIFO---------------------------------------------*/
fifo_allocate :-
    c_lang('retCode = ncFifoAllocate(inFifoHandle, deviceHandle, &inTensorDesc, 2);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').


fifo_create(X) :-
    atom(X),
    c_lang('retCode = ncFifoCreate(Jget_name(varX), NC_FIFO_HOST_WO, &inFifoHandle);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').


fifo_destroy :-
    c_lang('retCode = ncFifoDestroy(&inFifoHandle);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').




/*-------graph--------------------------------------------*/
load_graph_file(X) :-
    atom(X),
    c_lang('graphInMemory = LoadGraphFile(Jget_name(varX), &graphSizeInBytes);'),
    c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').


graph_allocate :-
    c_lang('ncGraphAllocate(deviceHandle, graphHandle, graphInMemory, graphSizeInBytes);'),
        c_lang('free(graphInMemory);').


graph_create(X) :-
    atom(X),
    c_lang('retCode = ncGraphCreate(Jget_name(varX), &graphHandle);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').    


graph_destroy :-
    c_lang('retCode = ncGraphDestroy(&graphHandle);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').

graph_queue_inference :-
    c_lang('retCode = ncGraphQueueInference(graphHandle, &inFifoHandle, 1, &outFifoHandle, 1);'),
    c_lang('if(retCode == NC_OK) '),
        c_lang('if(Jresolve_all(Jget_trail_end(),save2,nest+1) == YES)'),
        c_lang('return(YES);'),
        c_lang('Jset_tp(save1);'),
        c_lang('Junbind(save2);'),
        c_lang('return(NO);').