3

I would like to replace some of my calculations formerly written with armadillo with ArrayFire, in order to use some GPU capabilities. I do not want to replace everything, just the time-critical spots. Thus I need to convert armadillo-structures into arrayfire-structures and back. The first step is easy:

arma::colvec A_arma(5, arma::fill::ones);
af::array A_array(5, A_arma.memptr());//Done

Going back is more difficult. How do I get the data from the arrayfire-structure into the armadillo-structure? I can iterate over all elements and write them into the armadillo structure, but that would take a lot of time. Are there easier ways?

arc_lupus
  • 3,942
  • 5
  • 45
  • 81

2 Answers2

3

You can copy the data out of an af::array using the host member function. For example, you can copy the data from an ArrayFire array to a std::vector like this:

af::array gpu_data = af::randu(10, 10);
vector<float> cpu_data(gpu_data.elements());

gpu_data.host<float>(cpu_data.data());

This will copy the data in column major order to the cpu_data vector.

I am not too familiar with armadillo's data structure but I am sure you can pass the pointer returned by the memptr to the host function and the data will be copied into it.

Umar Arshad
  • 970
  • 1
  • 9
  • 22
0

You can convert directly to an Armadillo structure with the ArrayFire array's host pointer.

size_t nrows = 10;
size_t ncols = 10;

af::array af = af::constant(0, nrows, ncols); // defaults to dtype=f32
float* host_ptr = af.host<double>();
arma::fmat arma(host_ptr, nrows, ncols);

Notice that the types and sizes need to match. In the above case, single precision floating point type was used. For double precision, you would have to change to the following.

af::array af = af::constant(0, nrows, ncols, f64); // specify dtype=f64
double* host_ptr = af.host<double>();
arma::mat arma(host_ptr, nrows, ncols);

For complex vectors its a bit more complicated. Armadillo uses std::complex while ArrayFire uses a different data structure under the hood. These should be compatible (verify for your system) so using a reinterpret_cast should do the trick.

af::cfloat* host_ptr = img_af.host<af::cfloat>(); // Assuming dtype=c32
arma::cx_fmat arma(reinterpret_cast<std::complex<float>*>(host_ptr), nrows, ncols);

Last but not least, be sure to free the host pointer or you will have a memory leak!

af::freeHost(host_ptr);
nalyd88
  • 4,940
  • 8
  • 35
  • 51