2016-09-29 19 views
2

this answerへのフォローアップの質問として。私は、CPUのforループ実行をMetalのカーネル関数に置き換えて、計算を並列化してパフォーマンスを向上させようとしています。iOSメタルのMTLBufferで使用されるデータのメモリの割り当て

私の機能は基本的に畳み込みです。私は入力配列の値(データはAVCaptureSessionにあります)のために新しいデータを繰り返し受け取っているので、newBufferWithBytesNoCopy:length:options:deallocator:を使用すると、MTLBufferオブジェクトを作成することができます。ここに関連するコードは次のとおりです。

私は次のエラーを取得するこれを実行するとき
id <MTLBuffer> dataBuffer = [device newBufferWithBytesNoCopy:dataVector length:sizeof(dataVector) options:MTLResourceStorageModeShared deallocator:nil]; 
id <MTLBuffer> filterBuffer = [device newBufferWithBytesNoCopy:filterVector length:sizeof(filterVector) options:MTLResourceStorageModeShared deallocator:nil]; 
id <MTLBuffer> outBuffer = [device newBufferWithBytesNoCopy:outVector length:sizeof(outVector) options:MTLResourceStorageModeShared deallocator:nil]; 

failed assertion `newBufferWithBytesNoCopy:pointer 0x16fd0bd48 is not 4096 byte aligned.'

今、私はちょうど空の配列を作成(テスト目的のために)任意のメモリを割り当てますが、いないです固定サイズの浮動小数点数を計算し、乱数で埋めます。だから、私の主な質問は:

次の要件は、また、いくつかの追加の質問

This value must result in a page-aligned region of memory.

を満たしているように、私は山車のこれらの配列に正しい道を割り当てるにはどうすればよい:

  • んがnewBufferWithBytesNoCopyメソッドを使用してMTLBufferを作成するのは理にかなっているか、パフォーマンス上の問題ではないデータをコピーしていますか? (私の実際のデータは、ビデオフレームあたり約43'000 float値で構成されます。)
  • MTLResourceStorageModeShared APIリファレンスは

    The storage allocation of the returned new MTLBuffer object is the same as the pointer input value. The existing memory allocation must be covered by a single VM region, typically allocated with vm_allocate or mmap. Memory allocated by malloc is specifically disallowed.

    が、これは出力のみに適用されてい言うMTLResourceOptions

  • のために正しい選択ですまたはMTLBufferで使用されているすべてのオブジェクトのストレージ割り当てがmallocで行われていないかどうかを確認します。

答えて

4

ページアライメントされたメモリを割り当てる最も簡単な方法は、posix_memalignです。ここでは、ページ整列メモリでバッファを作成する完全な例です:

void *data = NULL; 
NSUInteger pageSize = getpagesize(); 
NSUInteger allocationSize = /* required byte count, rounded up to next multiple of page size */ pageSize * 10; 
int result = posix_memalign(&data, pageSize, allocationSize); 

if (result == noErr && data) { 
    id<MTLBuffer> buffer = [device newBufferWithBytesNoCopy:data 
                length:allocationSize 
                options:MTLResourceStorageModeShared 
               deallocator:^(void *pointer, NSUInteger length) 
                  { 
                   free(pointer); 
                  }]; 
    NSLog(@"Created buffer of length %d", (int)buffer.length); 
} 

あなたのデータがページ整列ポインタに到着することを保証することはできませんので、あなたはおそらくMTLBufferを配分したほうが良いでしょう無コピーバリアントを使用せずに、データを収容できるサイズのものを選択します。データのリアルタイム処理を行う必要がある場合は、各コマンドバッファが完了するのを待つのではなく、バッファのプールを作成してそれらの間で循環させる必要があります。 Sharedの保存モードは、これらの使用例に適しています。 mallocに関連した警告は、no-copyの場合にのみ適用されます。それ以外の場合、メタルはメモリを割り当てます。

+0

こんにちは@warrenmバッファを使ってサイクリングに関する簡単な質問。私はデータのリアルタイム処理をしたいのですが、 'AVCaptureVideoDataOutput'に' setAlwaysDiscardsLateVideoFrames:YES'を設定していますので、Metal部分を含む古いものの計算が終わる前に新しいフレームが決して処理されません。この場合、私はいつも同じものを使うことができるのでバッファのプールを作る必要はありませんか? –

+0

メタル処理でキャプチャ出力のキューをブロックしたくないので、Metalコマンドキューに処理を渡して非同期に実行します。フレームを処理する時間に応じて、一度に複数のフレームを飛行させることができます。その場合、読み書き競合や不要なブロックを避けるために、バッファプールを使用する必要があります。次のフレームが到着する前に常に(またはしばしば)処理を完了していることが判明した場合は、プールサイズを減らすか、まったく排除することもできます。 – warrenm

+0

私は分かりません。私は、上記の方法で遅れたビデオフレームを破棄することが正確に行うこと、すなわち、次のフレームが処理される前に処理が常に完了しなければならないことを強制し、早く到着するものを捨てると考えた。 –

関連する問題