在MacOS命令行程序中使用Metal

Posted on Apr 19, 2021

出错

最近在试验用GPU做计算,由于日常工作在MacBook Pro上,很自然想要试下Apple的Metal API

官方有个示例程序Performing Calculations on a GPU,很容易懂。下载示例代码到本地构建运行,完全正常。这么简单的吗?

那就开始用到自己的程序中吧!因为要与CPU/OpenCL等版本进行横向对比,很自然的Metal版本也使用了command line app的形式。代码写完编译很顺利,试跑一下,结果不对。。。

作为老程序员,遇到这种事情很淡定。即使是测试用的小程序,我也加上了错误处理相关的代码(良好的编程素养!),那看一下错误输出,查一下文档,一般都能搞定。

出错的代码位置是:

MTLCompileOptions* compileOptions = [MTLCompileOptions new];
id<MTLLibrary> lib = [device newLibraryWithSource:source
    options:compileOptions error:&error];
if (lib == nil)
{
    NSLog(@"Failed to create library: %@.", error);
    return nil;
}

而对应的错误输出为:

2021-04-19 22:00:10.546 estimate_pi_metal[3334:87426] Failed to create library: (null).

也就是:newLibraryWithSource执行失败返回了nil,与此同时error也为null。

官方文档

newLibraryWithSource官方文档上对Return Value的说明:

A new library object that contains the compiled source code or nil if an error occurred.

对error参数的说明:

A pointer to an error object that describes source code compilation problems, if any. 
This object contains compiler errors if the returned library object is nil, and compiler warnings if the library was generated with warnings. 
If the library was generated successfully, without errors or warnings, this error object is nil.

那现在是个啥情况?

各种猜测与排除

此处省略一万字。

结果

最后,在MTLCreateSystemDefaultDevice的说明文档上看到这么一段:

In macOS, in order for the system to provide a default Metal device object, you must link to the CoreGraphics framework. 
You usually need to do this explicitly if you are writing apps that don't use graphics by default, such as command line tools.

在CMakeLists.txt中加上target_link_libraries(target_name ... "-framework CoreGraphics")再试,世界和平了。