Objective c 使用金属时引发分段错误(Mac OS X 10.15.6)

Objective c 使用金属时引发分段错误(Mac OS X 10.15.6),objective-c,macos,metal,Objective C,Macos,Metal,我试图通过苹果的文档学习金属。到目前为止,我已经完成了一个计算4096个随机数平方根的应用程序的编写。但是,当我通过终端运行它时,它立即抛出一个分段错误 输出: 分段错误:11 注销 正在保存会话。。。 …复制共享历史。。。 …保存历史记录…截断历史记录文件。。。 …已完成。 [程序已完成] 到目前为止,我已经尝试在代码中几乎所有地方插入std::couts,我发现问题在于生成随机数的函数(generateRandomFloatData(id buffer)) 当我试图打印出输入缓冲区的地址时

我试图通过苹果的文档学习金属。到目前为止,我已经完成了一个计算4096个随机数平方根的应用程序的编写。但是,当我通过终端运行它时,它立即抛出一个分段错误

输出:

分段错误:11
注销
正在保存会话。。。
…复制共享历史。。。
…保存历史记录…截断历史记录文件。。。
…已完成。
[程序已完成]
到目前为止,我已经尝试在代码中几乎所有地方插入
std::cout
s,我发现问题在于生成随机数的函数(
generateRandomFloatData(id buffer)

当我试图打印出输入缓冲区的地址时,我得到了以下输出:

0x0
Segmentation fault: 11
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]
奇怪的是,它打印出一个空指针的地址

更多测试表明,更改函数以正确输入字符指针会输出指向字符串的地址
0x7ffee8bd8620

我的代码有问题吗

//
//  main.mm
//  MetalComputeCPP
//
//  Created by [] on 5/1/21.
//  Copyright © 2021 thng. All rights reserved.
//

#include <iostream>
#include <ApplicationServices/ApplicationServices.h>
#include <Metal/Metal.h>
#include <Foundation/Foundation.h>
#include <chrono>
const unsigned int arrayLength = 1 << 12;
const unsigned int bufferSize = arrayLength * sizeof(float);
void generateRandomFloatData(id<MTLBuffer> buffer) {
    std::cout << ((float*)buffer.contents) << "\n";
    float* dataPtr = ((float*)buffer.contents);
    for (unsigned long index = 0; index < arrayLength; index++)
    {
        dataPtr[index] = (float)((rand()/(float)(RAND_MAX))*10);
        std::cout << dataPtr[index] << "\n";
    }
}

int main(int argc, const char * argv[]) {
    id<MTLDevice> _mDevice = MTLCreateSystemDefaultDevice();
    
    
    NSError* error = nil;
    id<MTLLibrary> defaultLibrary = [_mDevice newDefaultLibrary];
    id<MTLFunction> SqrtFunction = [defaultLibrary newFunctionWithName:@"SqrtArray"];
    
    id<MTLComputePipelineState> _mSqrtFunctionPSO = [_mDevice newComputePipelineStateWithFunction: SqrtFunction error:&error];
    id<MTLCommandQueue> _mCommandQueue = _mDevice.newCommandQueue;
    
    id<MTLBuffer> _mBufferA = [_mDevice newBufferWithLength:bufferSize options:MTLResourceStorageModeShared];
    id<MTLBuffer> _mBufferResult = [_mDevice newBufferWithLength:bufferSize options:MTLResourceStorageModeShared];
    
    MTLSize gridSize = MTLSizeMake(arrayLength, 1, 1);
    NSUInteger threadGroupSize = _mSqrtFunctionPSO.maxTotalThreadsPerThreadgroup;
    if (threadGroupSize > arrayLength)
    {
        threadGroupSize = arrayLength;
    }
    MTLSize threadgroupSize = MTLSizeMake(threadGroupSize, 1, 1);
    
    generateRandomFloatData(_mBufferA);
    std::cout << "Generated random float data.\n";
    id<MTLCommandBuffer> commandBuffer = _mCommandQueue.commandBuffer;
    id<MTLComputeCommandEncoder> computeEncoder = [commandBuffer computeCommandEncoder];
    [computeEncoder setComputePipelineState:_mSqrtFunctionPSO];
    [computeEncoder setBuffer:_mBufferA offset:0 atIndex:0];
    [computeEncoder setBuffer:_mBufferResult offset:0 atIndex:1];
    [computeEncoder dispatchThreads:gridSize
    threadsPerThreadgroup:threadgroupSize];
    [computeEncoder endEncoding];
    [commandBuffer commit];
    std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
    [commandBuffer waitUntilCompleted];
    std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
    uint64_t time = std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count();
    
    
    float* a = ((float*)_mBufferA.contents);
    float* result = ((float*)_mBufferResult.contents);
    bool err = false;
    for (unsigned long index = 0; index < arrayLength; index++)
    {
        if (abs(result[index] - (float)sqrt(a[index])) > 0.0001) err = true;
        std::cout << "√" << a[index] << (err ? " != " : " = ") << result[index] << "\n";
    }
    std::cout << time << " nanoseconds\n";
    printf("Compute results as expected\n");
    return 0;
}
//
//main.mm
//MetalComputeCPP
//
//由[]于2012年5月1日创建。
//版权所有©2021 thng。版权所有。
//
#包括
#包括
#包括
#包括
#包括

generateRandomFloatData
中的const unsigned int arrayLength=1
缓冲区
nil
,因为
\u mBufferA
nil

\u mBufferA
nil
,因为
\u mDevice
nil

MTLCreateSystemDefaultDevice
返回
nil
因为(从)

在macOS中,为了使系统提供默认的金属设备对象,必须链接到CoreGraphics框架。如果您正在编写默认情况下不使用图形的应用程序,例如命令行工具,则通常需要明确执行此操作

你先前的问题:

为什么金属在通过终端运行时不起作用,但在通过Xcode运行时却很好

在Xcode
MTLCreateSystemDefaultDevice
中,在我的Mac上返回

_M设备:->-> 名称=英特尔高清图形4000

在终端中,MTLCreateSystemDefaultDevice返回

_M设备: 名称=英特尔高清图形4000

显然,Xcode将该设备包装在调试设备中,这有修复问题的副作用

//
//  File.metal
//  MetalComputeCPP
//
//  Created by [] on 5/1/21.
//  Copyright © 2021 thng. All rights reserved.
//

#include <metal_stdlib>
using namespace metal;
kernel void SqrtArray(device const float* inA,
                     device float* outB,
                     uint ind [[thread_position_in_grid]]) {
    //(x^n-k)' = (nx^(n-1))
    //f(x0)/f'(x0)
    outB[ind] = 0.1;
    for (int i = 0; i < 20; i++) {
        outB[ind] = outB[ind]-((outB[ind]*outB[ind]-inA[ind])/(outB[ind]*2));
    }
}