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