使用Metal(Mac OS X 10.15.6)时出现分段错误

哈尔普梅

我正在尝试通过Apple文档学习Metal。到目前为止,我已经完成了编写一个计算4096个随机数的平方根的应用程序。但是,当我通过终端运行它时,它将立即引发分段错误。

输出:

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

[Process completed]

到目前为止,我已经尝试将std::couts几乎插入所有代码中,并且发现问题出在生成随机数(generateRandomFloatData(id<MTLBuffer> buffer)的函数上

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

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

[Process completed]

奇怪的是,它打印出NULL指针的地址。

更多测试显示,更改功能以正确输入char指针会输出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;
}
//
//  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));
    }
}
维莱克

buffergenerateRandomFloatDatanil因为_mBufferAnil

_mBufferAnil因为_mDevicenil

MTLCreateSystemDefaultDevice返回,nil因为(来自MTLCreateSystemDefaultDevice

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

您之前的问题:

为什么通过终端运行Metal时不起作用,而通过Xcode运行时则很好?

MTLCreateSystemDefaultDeviceMac上的Xcode中返回

_mDevice:<CaptureMTLDevice:0x10050bbb0>-> <MTLDebugDevice:0x10050aae0>-> <MTLIGAccelDevice:0x1031c8000>名称= Intel HD Graphics 4000

在终端MTLCreateSystemDefaultDevice退货

_mDevice:<MTLIGAccelDevice:0x7f9c32f17000>名称= Intel HD Graphics 4000

Apparenlty Xcode将设备包装在调试设备中,这具有解决问题的副作用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章