2016-09-29 29 views
2

作爲this answer的後續問題。我試圖用Metal中的內核函數替換運行在CPU上的for-loop來並行化計算並提高性能。在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浮點值。)
  • MTLResourceStorageModeSharedMTLResourceOptions
  • 正確的選擇的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.

    這是否僅適用於輸出緩衝區,還是應該與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相關的警告僅適用於非複製情況,因爲在其他情況下,金屬會爲您分配內存。

+0

嗨@warrenm關於循環雖然緩衝區一個簡單的問題。我希望實時處理數據,但是我在'AVCaptureVideoDataOutput'上設置了'setAlwaysDiscardsLateVideoFrames:YES',所以在我完成包括Metal部分在內的所有舊計算之前,永遠不會處理新幀。在這種情況下,是否需要創建一個緩衝池,因爲我總是可以使用相同的緩衝區? –

+0

您不希望在Metal處理中阻止捕獲輸出隊列,因此您將工作交給Metal命令隊列以異步執行。根據處理幀需要多長時間,您可能會同時有多個幀在飛行。如果是這樣的話,你仍然應該使用緩衝池來避免讀寫衝突或不必要的阻塞。如果你發現你總是(或經常)在下一幀到來之前完成處理,你可以減少池的大小,甚至完全消除它。 – warrenm

+0

我不明白。我認爲用上面提到的方法丟棄晚期視頻幀確實是這樣的,即強制處理總是必須在處理下一幀之前完成,並丟棄早到的東西。 –