Search code examples
c++arrayfire

Retrieving data from af::array via host() results in wrong data


When trying to retrieve data from an af::array (arrayfire) from the device via host(), my output data on the host is wrong (i.e. wrong values). For testing that, I wrote a small code sample (based on https://stackoverflow.com/a/29212923/2546099):

int main(void) {  
    size_t vector_size = 16;
    af::array in_test_array = af::constant(1., vector_size), out_test_array = af::constant(0., vector_size);

    af_print(in_test_array);
    double *local_data_ptr = new double[vector_size]();

    for(int i = 0; i < vector_size; ++i)
        std::cout << local_data_ptr[i] << '\t';
    std::cout << '\n';
    in_test_array.host(local_data_ptr);
    for(int i = 0; i < vector_size; ++i)
        std::cout << local_data_ptr[i] << '\t';
    std::cout << '\n';
    delete[] local_data_ptr;
    out_test_array = in_test_array;
    af_print(out_test_array);
    return 0;
}

My output is

in_test_array
[16 1 1 1]
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 

0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0
0.007813        0.007813        0.007813        0.007813        0.007813        0.007813        0.007813        0.007813        0       0       0       0       0       0       0       0
out_test_array
[16 1 1 1]
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000 
    1.0000

Why are half the values in the pointer set to 0.007813, and not all values to 1? When changing the default value for in_test_array to 2, half the values are set to 2, and for 3 those values are set to 32. Why does that happen?


Solution

  • The datatypes between arrayfire and C are in conflict.

    For float use:

    af::array in_test_array = af::constant(1., vector_size), 
              out_test_array = af::constant(0., vector_size);
    float *local_data_ptr = new float[vector_size]();
    

    For double use:

    af::array in_test_array = af::constant(1., vector_size, f64),
              out_test_array = af::constant(0., vector_size, f64)
    double *local_data_ptr = new double[vector_size]();
    

    IN both cases above, you will see that arrayfire will return you 1.0 in the local_data_ptr buffer, although with different data types.