我试图让一个神经网络在金属上运行 . 基本思想是数据重复 . 每个gpu线程为随机数据点运行一个网络版本 .
我写过其他着色器工作正常 .
我还在c命令行应用程序中尝试了我的代码 . 没有错误 . 也没有编译错误 .
我使用apple文档转换为metal c,因为不支持c 11中的所有内容 .
它在加载内核函数后以及在尝试将 newComputePipelineStateWithFunction
分配给金属设备时崩溃 . 这意味着在编译时未捕获的代码存在问题 .
MCVE:
kernel void net(const device float *inputsVector [[ buffer(0) ]], // layout of net *
uint id [[ thread_position_in_grid ]]) {
uint floatSize = sizeof(tempFloat);
uint inputsVectorSize = sizeof(inputsVector) / floatSize;
float newArray[inputsVectorSize];
float test = inputsVector[id];
newArray[id] = test;
}
Update
它与动态数组有关 .
由于它无法创建管道状态并且不会崩溃运行实际着色器,因此它必须是编码问题 . 不是输入问题 .
将动态数组中的值分配给缓冲区会使其失败 .
2 回答
The real problem: It is a memory issue!
对于所有人说这是一个记忆问题,你是对的!这里有一些伪代码来说明它 . 对不起,它在“Swift”中,但更容易阅读 . 金属着色器有一种时髦的生活方式 . 它们首先被初始化而没有值来获取内存 . 这一步失败了,因为它依赖于后面的步骤:设置缓冲区 .
这一切都归结为何时可用的值 . 我对
newComputePipelineStateWithFunction
的理解是错误的 . 它不仅仅是获取着色器功能 . 这也是初始化过程中的一小步 .Fix:
我终于意识到缓冲区在技术上是动态数组,而不是在着色器中创建数组,我也可以添加更多缓冲区 . 这显然有效 .
我认为你的问题在于这一行:
这里
schemeVector
是 dynamic 所以as in classic C++你不能在动态数组上使用sizeof
来获取元素数量 .sizeof
仅适用于您在金属着色器代码中本地/静态定义的数组 .想象一下它是如何在内部工作的:在编译时,Metal编译器应该将
sizeof
调用转换为常量......但是他不能,因为schemeVector
是着色器的参数,因此可以有任何大小......所以对我来说,解决方案是在代码的C / ObjectiveC / Swift部分计算
schemeVectorSize
,并将其作为参数传递给着色器(作为OpenGLES术语中的统一......) .