Возникли проблемы с MPSMatrixMultiplication encodeToBuffer - PullRequest
0 голосов
/ 25 февраля 2019

Я использую 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

Буду признателен, если просто укажете на проблему, с которой я столкнулся в своем коде.

1 Ответ

0 голосов
/ 25 февраля 2019

Это странное сообщение об ошибке, которое само по себе заслуживает сообщения об ошибке.

Проблема в том, что вы вручную заполняете свои матричные дескрипторы, но не инициализируете все необходимые поля,В частности, каждый из ваших дескрипторов матрицы имеет свои свойства matrices и matrixBytes, установленные на 0, что является недопустимой конфигурацией.

Хотя эти свойства, кажется, не проверяются во время создания матрицы, онипохоже, что проверяется во время кодирования, что приводит к этой ошибке.По моему мнению, во время создания матрицы должна быть более строгая проверка, но поскольку MPSMatrix является такой легкой оболочкой для буфера, это, вероятно, не было сочтено необходимым.

В любом случаеЛучший способ избежать этого - использовать метод фабрики дескрипторов матриц, чтобы заполнить оставшиеся поля.Это меньше кода, и это более стильно.Например:

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

Кроме того, у вас, похоже, есть ошибка в вызовах создания и кодирования ядра: resultColumns должно быть 3, а не 1;leftMatrix должно быть ArightMatrix должно быть B, чтобы получить матрицу результатов 3x3.

...