Having problem with MPSMatrixMultiplication encodeToBuffer



我正在使用mpsmatrixmultiplication,当我调用encodetocommandbuffer时,它在说明错误"启动矩阵必须包含在每个mpsmatrix对象中"。我不确定这是什么意思。

我只是想进行一个简单的计算,如果我在swift中应用类似的代码和模式,它可以很好地工作,但是在Objective-C中,它给了我错误。

    #import <Foundation/Foundation.h>
    #import <Metal/Metal.h>
    #import <MetalKit/MetalKit.h>
    #import <MetalPerformanceShaders/MetalPerformanceShaders.h>
    NS_ASSUME_NONNULL_BEGIN
     //Interface
    @interface KernelCalculator: NSObject
    ///Properties
    @property id<MTLDevice> device;
    @property id<MTLBuffer> bufferA;
    @property id<MTLBuffer> bufferB;
    @property id<MTLBuffer> bufferC;
    @property MTKView *view;
    @property id<MTLCommandQueue> commandQueue;
    @property id<MTLCommandBuffer> commandBuffer;
    @property MPSMatrixMultiplication *mmKernel;
    @end
    NS_ASSUME_NONNULL_END

    #import "KernelCalculator.h"
    @implementation KernelCalculator
    - (instancetype)init
    {
       self = [super init];
       if (self) 
     {
        _view = [[MTKView alloc] init];
        _view.device = MTLCreateSystemDefaultDevice();
        if(!_view.device){
             NSLog(@"Metal is not supported on this device");
            return self;
        }
        _device = _view.device;
        _commandQueue = [_device newCommandQueue];
        _commandBuffer = [_commandQueue commandBuffer];
//Float array A
        float _matrix_A[] = {
            2.0, 3.0, 4.0
        };
//Float array B
        float _matrix_B[] = {
            2.0, 2.0, 2.0
        };
//size of each array
        int matrix_A_length= sizeof(_matrix_A)/sizeof(float);
        int matrix_B_length= sizeof(_matrix_B)/sizeof(float);
        ///<A>
        int totalBytesA = sizeof(_matrix_A);
        _bufferA = [_device newBufferWithBytes:_matrix_A length:totalBytesA options: MTLResourceCPUCacheModeDefaultCache];
        MPSMatrixDescriptor *descriptionA = [[MPSMatrixDescriptor alloc] init];
        [descriptionA setRows:3];
        [descriptionA setColumns:1];
        [descriptionA setRowBytes:totalBytesA/3];
        [descriptionA setDataType:MPSDataTypeFloat32];
        MPSMatrix *A = [[MPSMatrix alloc] initWithBuffer:_bufferA descriptor:descriptionA];
        printf("n A row: %lu ", (unsigned long)A.rows);
        printf("n A columns: %lu ", (unsigned long)A.columns);
        printf("n A rowBytes: %lu", (unsigned long)A.rowBytes);
        printf("n A totalBytes: %lu nn", (unsigned long)totalBytesA);
        ///</A>
        ///<B>
        int totalBytesB = sizeof(_matrix_B);
        _bufferB = [_device newBufferWithBytes:_matrix_B length:totalBytesB options: MTLResourceCPUCacheModeDefaultCache];
        MPSMatrixDescriptor *descriptionB = [[MPSMatrixDescriptor alloc] init];
        [descriptionB setRows:1];
        [descriptionB setColumns:3];
        [descriptionB setRowBytes:totalBytesB/1];
        [descriptionB setDataType: MPSDataTypeFloat32];
        MPSMatrix *B = [[MPSMatrix alloc] initWithBuffer:_bufferB descriptor:descriptionB];
        printf("n B row: %lu ", (unsigned long)B.rows);
        printf("n B columns: %lu ", (unsigned long)B.columns);
        printf("n B rowBytes: %lu", (unsigned long)B.rowBytes);
        printf("n B totalBytes: %lu nn", (unsigned long)totalBytesB);
        ///</B>
        ///<C>
        int totalBytesC = matrix_A_length* matrix_B_length*sizeof(float);
        _bufferC = [_device newBufferWithLength:totalBytesC options:MTLResourceCPUCacheModeDefaultCache];
        MPSMatrixDescriptor *descriptionC = [[MPSMatrixDescriptor alloc] init];
        [descriptionC setRows:A.rows];
        [descriptionC setColumns:B.columns];
        [descriptionC setRowBytes:totalBytesC/A.rows];
        [descriptionC setDataType: MPSDataTypeFloat32];
        MPSMatrix *C = [[MPSMatrix alloc] initWithBuffer:_bufferC descriptor:descriptionC];
        printf("n C row: %lu ", (unsigned long)C.rows);
        printf("n C columns: %lu ", (unsigned long)C.columns);
        printf("n C rowBytes: %lu", (unsigned long)C.rowBytes);
        printf("n C totalBytes: %lu nn", (unsigned long)totalBytesC);
        ///</C>
        _mmKernel = [[MPSMatrixMultiplication alloc]
            initWithDevice:_device
            transposeLeft:false
            transposeRight:false
            resultRows:3
            resultColumns:1
            interiorColumns:1
            alpha:1.0
            beta:0.0];
        [_mmKernel encodeToCommandBuffer: _commandBuffer leftMatrix:B rightMatrix:A resultMatrix:C];
        [_commandBuffer commit];
        [_commandBuffer waitUntilCompleted];
    }
    return self;
    }
    @end

,如果只指出我在代码中遇到的问题,我会很感激。

这是一条奇异的错误消息,值得一个错误报告。

问题是您正在手动填写矩阵描述符,但您并未初始化所有必要的字段。特别是,您的矩阵描述符每个将其matricesmatrixBytes属性设置为0,这是无效的配置。

尽管这些属性似乎没有在矩阵创建时间检查,但它们似乎在编码时间确实得到了验证,从而导致了这一故障。我认为,在创建矩阵时应该进行更严格的验证,但是由于MPSMatrix是缓冲区周围的轻量级包装器,因此这可能不是必需的。

无论如何,避免这种情况的最佳方法是使用矩阵描述符工厂方法为您填写其余字段。它的代码少,而且更时尚。例如:

MPSMatrixDescriptor * descriptionA =
    [MPSMatrixDescriptor matrixDescriptorWithRows:3
                                          columns:1
                                         rowBytes:totalBytesA/3
                                         dataType:MPSDataTypeFloat32];

另外,您似乎在内核创建和编码呼叫中遇到了错误:resultColumns应为3,而不是1;leftMatrix应为A; rightMatrix应该为b,以产生3x3结果矩阵。

最新更新