0

我正在使用 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 \n\n", (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 \n\n", (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 \n\n", (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

如果能指出我的代码中存在的问题,我将不胜感激。

4

1 回答 1

1

这是一个奇怪的错误消息,值得单独报告一个错误报告。

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

尽管在矩阵创建时似乎没有检查这些属性,但它们似乎在编码时得到了验证,从而导致了此失败。在我看来,在创建矩阵时应该进行更严格的验证,但由于MPSMatrix缓冲区如此轻量级的包装,这可能被认为没有必要。

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

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

此外,您的内核创建和编码调用似乎有错误:resultColumns应该是 3,而不是 1;leftMatrix应该是A;并且rightMatrix应该是 B,以生成 3x3 结果矩阵。

于 2019-02-25T17:56:23.877 回答