頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


Metal Performance Shaderで同期処理っぽく記述する

機械学習などでMetal Performance Shaderを使ってNNの計算をする時、GPUに渡してそれが終わったら結果が得られるようになるって流れなので、コードの見通しが悪くなる。

a = [self inference:s];

ってな感じで記述できればいいんだけど、実際は

[self inference:s];

ってしといて結果が出た後の処理は別なところに書かないといけない↓
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
    //続きはこんなところ!
}];
なんとかならないのかなあと思ったらsemaphoreなる仕組みがある。

Objective-Cで非同期処理を同期処理にする方法。 | 三度の飯とエレクトロン

↑これを参考にてコードを書き直してみたところ、、、

a = [self inference:s];

という感じの記述ができて意図通り動いた!
計算に時間がかかるとまずい場合もあるかもしれないが、今やってることに対しては計算時間も短く問題なさそう。


コードはざっくりこんな感じ。勝手な構造体なんかは気にしないで。
-(MPSResult_t)inferenceForInputs:(Inputs_t)inputs
{
    __block MPSResult_t mpsResult;

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        
        [self->srcImage.texture replaceRegion:self->srcImageRegion
                            mipmapLevel:0
                                  slice:0
                                    withBytes:self->angles
                            bytesPerRow:sizeof(float)*4
                          bytesPerImage:0];
        
        @autoreleasepool{
            id <MTLCommandBuffer> commandBuffer = [self->commandQueue commandBuffer];
            
            [self->h1 encodeToCommandBuffer:commandBuffer sourceImage:self->srcImage destinationImage:self->h1Image];
            [self->h2 encodeToCommandBuffer:commandBuffer sourceImage:self->h1Image destinationImage:self->finalImage];
            
            [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
                
                [self->finalImage.texture getBytes:&self->qResults[0]
                                 bytesPerRow:sizeof(float)*4
                                        fromRegion:self->filnalImageRegion
                                 mipmapLevel:0];
                
                mpsResult.q0 = self->qResults[0];
                mpsResult.q1 = self->qResults[1];
                
                dispatch_semaphore_signal(semaphore);//止めてたのを終える
                
            }];
            
            [commandBuffer commit];
        }
    });
    
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//これで止める
    
    return mpsResult;//結果が出てからリターンする
}

<< コストコのクロスバイクを調整してもらった  TopPage  コストコでクロスバイクを買った >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/1143-08b31737




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad