No matching function to call 'createMatrix'

141 views Asked by At

What I'm trying to do

I'm trying to convert a buffer of type [Int] to [[Int]]. Since arrays are not super easy to return in C, I'm creating a new empty array and passing the pointer into a void function that is supposed to fill the address space with Integers from the buffer.

Afterwards, the matrices are supposed to get added and the result written into a result buffer.

The problem

For some reason, it can't find my function. I'm kind of new to c++ so excuse me when it's something simple I'm overlooking here. The function is not part of a class. So technically it should be in the same namespace?

#include <metal_stdlib>
using namespace metal;



void createMatrix(device int **arr, int count, int buff[]) {
    for(int i = 0; i < count; i++)
     for(int j = 0; j < count; j++)
        arr[j][i] = buff[i + j];
}


kernel void addition_compute_function(constant int *arr1        [[ buffer(0) ]],
                                      constant int *arr2        [[ buffer(1) ]],
                                      device   int *resultArray [[ buffer(2) ]],
                                               uint   index [[ thread_position_in_grid ]]) {



    int array1[6][6] = {{0}};
    createMatrix(**array1, 6, *arr1); // ERROR: No matching function for call to 'createMatrix'
    
    int array2[6][6] = {{0}};
    createMatrix(**array2, 6, *arr2); // ERROR: No matching function for call to 'createMatrix'

    for (int i = 1; i <= 6; i++){
            resultArray[i][index] = array1[i][index] + array2[i][index]; // ERROR: Subscripted value is not an array, pointer, or vector
    }

}

What I tried

Most questions regarding this error are concerning methods of a class getting called after an object is initialized. This isn't the case here, so no dice thus far in researching the problem.

Edit, incorporated feedback

#include <metal_stdlib>
using namespace metal;



void createMatrix(device int (*arr)[6], int count,constant int* buff) {
    for(int i = 0; i < count; i++)
     for(int j = 0; j < count; j++)
        arr[j][i] = buff[i + j];
}


kernel void addition_compute_function(constant int *arr1        [[ buffer(0) ]],
                                      constant int *arr2        [[ buffer(1) ]],
                                      device   int *resultArray [[ buffer(2) ]],
                                               uint   index [[ thread_position_in_grid ]]) {



    int array1[6][6] = {{0}};
    createMatrix(array1, 6, arr1); //ERROR: No matching function for call to 'createMatrix'
    
    int array2[6][6] = {{0}};
    createMatrix(array2, 6, arr2); //ERROR: No matching function for call to 'createMatrix'

    int tempResultArray[6][6] = {{0}};
    
    // I want to do some stuff here I find the 2d array form more convientient to work with, therefore the back and forth
    for (int i = 1; i <= 6; i++){
            tempResultArray[i][index] = array1[i][index] + array2[i][index];
    }
    
    for (int i = 1; i <= 6; i++){
        for (int j = 1; j <= 6; j++){
            resultArray[i+j] = tempResultArray[i][j];
            
    }
}

Edit2

I gave up, nothing worked. I can't find the reason the function was is not recognized. I don't even know if it's the way I'm calling the function/populating the parameters, or if the namespace is wrong. Documentation for this behavior is lacking. Ended up hardcoding the function to create a 2d array from 1d array and vice versa.

3

There are 3 answers

1
Hamid Yusifli On BEST ANSWER

Any variable that is a pointer or reference must be declared with one of the address space attributes.

This is the correct implementation of your function:

void createMatrix(device int (*arr)[6][6], int count, constant int* buff) {
    for(int i = 0; i < count; i++)
        for(int j = 0; j < count; j++)
            (*arr)[j][i] = buff[i + j];
}

Kernel:

device int (*array1)[6][6] = {{0}};
createMatrix(array1, 6, arr1);
3
john On

Like this

void createMatrix(int (*arr)[6], int count, int* buff)

and you call it like this

createMatrix(array1, 6, arr1);

2D arrays and double pointers are not the same thing at all.

I've no idea about your final loop. Obviously if resultArray is a 1D array, then you cannot do resultArray[x][y] on it.

0
gueldi On

In addition to @john's answer I'd suggest allocating the memory statically beforehand otherwise this will segvault.

Try this:

int array1[6][6] = {0}; // this is the static allocation (not sure if your need 'device' here)
createArray(&array1, 6, arr1);

Not this:

// this will only set the address to 0x0 and if dereferenced in the function segvaults
device int (*array1)[6][6] = {{0}};