我需要在STL中爲我的金屬計算內核所描述的upper_bound
的實現。由於沒有金屬標準庫什麼,我基本上是從<algorithm>
它複製到我的着色器文件像這樣:是否有我的iOS金屬計算內核的編譯器錯誤,或者我錯過了什麼?
static device float* upper_bound(device float* first, device float* last, float val)
{
ptrdiff_t count = last - first;
while(count > 0){
device float* it = first;
ptrdiff_t step = count/2;
it += step;
if(!(val < *it)){
first = ++it;
count -= step + 1;
}else count = step;
}
return first;
}
我創建了一個簡單的內核來測試它像這樣:
kernel void upper_bound_test(
device float* input [[buffer(0)]],
device uint* output [[buffer(1)]]
)
{
device float* where = upper_bound(input, input + 5, 3.1);
output[0] = where - input;
}
這對於本測試具有硬編碼的輸入大小和搜索值。我還硬編碼了框架端的5個元素輸入緩衝區,如下所示。我希望這個內核返回第一個輸入的索引大於3.1
這是行不通的。事實上,output[0]
永遠不會被寫入 - 因爲我用一個幻數預先加載了緩衝區,看它是否被覆蓋。它沒有。在waitUntilCompleted
後其實commandBuffer.error
看起來是這樣的:
Error Domain = MTLCommandBufferErrorDomain
Code = 1
NSLocalizedDescription = "IOAcceleratorFamily returned error code 3"
是什麼錯誤代碼3是什麼意思?在有機會完成之前,我的內核是否被殺死了?
此外,我試過的upper_bound
像這樣只是線性搜索版本:
static device float* upper_bound2(device float* first, device float* last, float val)
{
while(first < last && *first <= val)
++first;
return first;
}
這一個工程(排序的)。我有一個從<algorithm>
的二分查找lower_bound的相同問題 - 是一個天真的線性版本的作品(排序)。順便說一句,我測試了我的STL複製版本的直接C代碼(顯然刪除了device
),並且它們在着色器之外很好地工作。請告訴我我做錯了,這不是一個金屬編譯器錯誤。現在關於上面的「排序」:線性搜索版本在5s和mini-2(A7s)上工作(在上面的例子中返回索引3),但是在6+(A8)上它給出了正確的答案+ 2^31。有沒有搞錯!相同的確切代碼。注意框架方面,我使用uint32_t
,在着色器方面我使用uint
- 這是同樣的事情。還要注意,每個指針減法(ptrdiff_t
都是有符號的8字節的東西)都是小的非負值。爲什麼高階的6+設置位?當然,爲什麼我的真正的二進制搜索版本不工作?
這裏是框架端的東西:
id<MTLFunction> upperBoundTestKernel = [_library newFunctionWithName: @"upper_bound_test"];
id <MTLComputePipelineState> upperBoundTestPipelineState = [_device
newComputePipelineStateWithFunction: upperBoundTestKernel
error: &err];
float sortedNumbers[] = {1., 2., 3., 4., 5.};
id<MTLBuffer> testInputBuffer = [_device
newBufferWithBytes:(const void *)sortedNumbers
length: sizeof(sortedNumbers)
options: MTLResourceCPUCacheModeDefaultCache];
id<MTLBuffer> testOutputBuffer = [_device
newBufferWithLength: sizeof(uint32_t)
options: MTLResourceCPUCacheModeDefaultCache];
*(uint32_t*)testOutputBuffer.contents = 42;//magic number better get clobbered
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
id<MTLComputeCommandEncoder> commandEncoder = [commandBuffer computeCommandEncoder];
[commandEncoder setComputePipelineState: upperBoundTestPipelineState];
[commandEncoder setBuffer: testInputBuffer offset: 0 atIndex: 0];
[commandEncoder setBuffer: testOutputBuffer offset: 0 atIndex: 1];
[commandEncoder
dispatchThreadgroups: MTLSizeMake(1, 1, 1)
threadsPerThreadgroup: MTLSizeMake(1, 1, 1)];
[commandEncoder endEncoding];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
uint32_t answer = *(uint32_t*)testOutputBuffer.contents;
看起來像一個bug給我。你有沒有向蘋果公司提交錯誤報告? – warrenm
@warrenm感謝您的關注Warren,我想在發佈bug之前先將它發送給SO和dev-forums。目前金屬似乎是一個在線幽靈城 - 在這兩個地方。我買了你的書來支持你的工作,並幫助我開始。 – Mustang