Metal Performance Shaderで同期処理っぽく記述する
機械学習などでMetal Performance Shaderを使ってNNの計算をする時、GPUに渡してそれが終わったら結果が得られるようになるって流れなので、コードの見通しが悪くなる。
a = [self inference:s];
ってな感じで記述できればいいんだけど、実際は
[self inference:s];
ってしといて結果が出た後の処理は別なところに書かないといけない↓
Objective-Cで非同期処理を同期処理にする方法。 | 三度の飯とエレクトロン
↑これを参考にてコードを書き直してみたところ、、、
a = [self inference:s];
という感じの記述ができて意図通り動いた!
計算に時間がかかるとまずい場合もあるかもしれないが、今やってることに対しては計算時間も短く問題なさそう。
コードはざっくりこんな感じ。勝手な構造体なんかは気にしないで。
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;//結果が出てからリターンする }
スポンサーサイト