copy host memory into an array?

[Old posts from the commercial version of ArrayFire] Discussion of ArrayFire using CUDA or OpenCL.

Moderator: pavanky

copy host memory into an array?

Postby jon_atl » Tue Feb 18, 2014 8:42 am

Ok, this is a stupid-simple question, but I honestly don't see an example for it. Sure I just missed it, of course!

All I'm looking to do is to copy data from a host memory buffer into an existing array:

// construct an empty array
array a;

// create a host memory buffer
float* x = (float*)malloc(sizeof(float)*10);

// do something to load data into x
...

// now, copy x -> a
???????????

I see examples of things like this:
array a(1,10, x);
But I'm not looking to initialize an array... I'm looking to over-write an existing array.
jon_atl
 
Posts: 1
Joined: Tue Feb 18, 2014 8:20 am

Re: copy host memory into an array?

Postby shehzan » Tue Feb 18, 2014 10:53 am

Hi.

One way of doing this is as follows:

Code: Select all
//Allocate x
//Do operations on x on the host side
array new_array(<size>, x);
existing_array = new_array;  // This line is a shallow copy and will assign the existing_array variable to the new_array variable. Essential a no-op. The data of the existing_array before assignment will be deleted.


Another way to do this would be to use cudaMemcpy. You can retrieve the device pointer from the existing_array and do a cudaMemcpy from host to device.
If you are interested in going this route, I can elaborate further on it.
Note: I would suggest this way only if you have custom CUDA code as a part of your source code.

If you wish to, you can post a code snippet here and I can give you the best way to go about it.
----
Shehzan
Developer
AccelerEyes
User avatar
shehzan
 
Posts: 121
Joined: Tue Feb 12, 2013 7:20 pm

Re: copy host memory into an array?

Postby neuralPanther » Wed Feb 19, 2014 6:55 pm

In the interest of not starting a new thread - I'm also essentially attempting to do the same thing.

I have data that I read out of a file, push to the GPU (using CudaMemcpy) and run a custom kernel on, I would like to then use arrayFire functions (say perform an FFT) but it's not clear how to go about this.

For example I have something similar to the following:
Code: Select all
// File Read and Memory allocation and then:
Complex* d_signal; // get's malloc'd during memory allocation


checkCudaErrors(cudaMemcpy(d_rawData,h_signal,N,cudaMemcpyHostToDevice)); //h_signal is the host signal

//Call custom kernel
cudaCustomKernel(d_rawData, d_signal, SIGNAL_SIZE); // input is d_rawData, output is d_signal

// call arrayFire function(s) on d_signal


let's say we wanted to call af::fir on d_signal, or af::fft on d_signal - how would we do this?

If we need to copy d_signal to an af::array how would we do this?
neuralPanther
 
Posts: 25
Joined: Fri Feb 14, 2014 8:03 pm

Re: copy host memory into an array?

Postby pavanky » Thu Feb 20, 2014 4:34 pm

Hi,

You can do something like this:

Code: Select all
float host_ptr[] = {0,1,2,3,4,5}; // column-major order (like Fortran)

// Create array from host memory
array a(2, 3, host_ptr); // f32 matrix of size 2-by-3 from host data

float *device_ptr;
cudaMalloc((void**)&device_ptr, 6*sizeof(float));
cudaMemcpy(device_ptr, host_ptr, 6*sizeof(float), cudaMemcpyHostToDevice);

// Create array from device memory
array b(2,3, host_ptr, afDevice); // Note: afDevice (default: afHost)
// do not call cudaFree(device_ptr) -- it is freed when 'b' is destructed.


Please note the last line. Do not use cudaFree on the device pointer you hand over to ArrayFire. This will cause double free issues.

The suggested way for your problem is to do something like this:

Code: Select all
array signal(N);
array rawData(N, h_signal);
Complex *d_rawData = rawData.device<Complex>();
Complex *d_signal = signal.device<Complex>();

// launch custom kernels
rawData.unlock();
signal.unlock();

// Use ArrayFire.


This way ArrayFire handles the memory copies as well as memory allocation. You can just plugin your custom kernel when you need it.
Pavan Yalamanchili,
ArrayFire
--
~ If it is not broken, you have not tried hard enough ~
User avatar
pavanky
Site Admin
 
Posts: 1123
Joined: Mon Mar 15, 2010 7:39 pm
Location: Atlanta, GA

Re: copy host memory into an array?

Postby pavanky » Thu Feb 20, 2014 4:38 pm

For future reference, please read through our getting started page:
http://www.accelereyes.com/arrayfire/c/ ... tarted.htm

This particular section is referenced under here:
http://www.accelereyes.com/arrayfire/c/ ... tm#dev_ptr
Pavan Yalamanchili,
ArrayFire
--
~ If it is not broken, you have not tried hard enough ~
User avatar
pavanky
Site Admin
 
Posts: 1123
Joined: Mon Mar 15, 2010 7:39 pm
Location: Atlanta, GA

Re: copy host memory into an array?

Postby neuralPanther » Sat Feb 22, 2014 11:04 pm

Thank you for a detailed reply that was very helpful.

I'm still not clear on a few things (after going through the getting started guide in more detail)

Code: Select all
// Create array from host memory
array a(2, 3, host_ptr); // f32 matrix of size 2-by-3 from host data

This method works if I'm allocating the array with the host_ptr but what if my array is already created?

Could I do something like:
Code: Select all
// in myClass.h
af::array* af_signal;


Code: Select all
// in myClass.cpp constructor
af_signal = new af::array(1,signalSize,af::c64);

// in a GetDataFunction
memcpy(h_signal,dataArray,signalLength);// copy from a file buffer to the host buffer
checkCudaErrors(cudaMemcpy(af_signal,h_signal,signalLength,cudaMemcpyHostToDevice)); // this doesn't seem right -

//should I use af_signal(span) = h_signal? - this also doesn't seem correct


I haven't found a place in the documentation or examples that provides a good walkthrough of this process in particular.

I understand how the data copy works if I am generating the array (like you posted above) but not how to update the array, from the host, once the array has been generated ...
neuralPanther
 
Posts: 25
Joined: Fri Feb 14, 2014 8:03 pm

Re: copy host memory into an array?

Postby pavanky » Sun Feb 23, 2014 1:38 pm

Hi,

Code: Select all
array A(3, 4, h_ptr);


This copies data from host to device and then creates arrayfire array.

Code: Select all
array A(3, 4, d_ptr, afDevice);


This uses the existing device pointer and creates an arrayfire array around it.

Code: Select all
ty *d_ptr = A.device<ty>();


This gets the device pointer from arrayfire array. There is no copy being done.

Code: Select all
ty *h_ptr = A.host<ty>();


This allocates memory on the host and copies data from the device to host memory.

Code: Select all
A.host(h_ptr);


This uses already allocated host pointer and copies from the device to the host. No allocation is done.

This should cover all use cases you are considering :)
Pavan Yalamanchili,
ArrayFire
--
~ If it is not broken, you have not tried hard enough ~
User avatar
pavanky
Site Admin
 
Posts: 1123
Joined: Mon Mar 15, 2010 7:39 pm
Location: Atlanta, GA

Re: copy host memory into an array?

Postby neuralPanther » Sun Feb 23, 2014 11:29 pm

Excellent - thank you -

I ended up doing the following (just to close the loop)

Code: Select all
array af_Data =  af::array(1,signalSize,af::c64);

// point device pointer
(cdouble*) d_signal = (cdouble*) af_Data.device<cdouble>();

//copy the host data in
cudaMemcpy(d_signal, host_array, sizeofData, cudamemcpyhosttodevice);

// run custom kernels then
af_Data.unlock()

// do stuff with Array Fire then:
 d_signal = (cdouble*) af_Data.device<cdouble>();

// do my openGL interop stuff ....
checkCudaErrors(cudaGraphicsMapResources(1,&cuda_GL_signal_resource,0));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&d_plotPtr, &numBytes, cuda_GL_signal_resource));

checkCudaErrors(cudaMemcpy(d_plotPtr, d_signal,(signalSize)*2*sizeof(double),cudaMemcpyDeviceToDevice));

checkCudaErrors(cudaGraphicsUnmapResources(1,&cuda_GL_signal_resource,0));


Again thanks for your assistance :)
neuralPanther
 
Posts: 25
Joined: Fri Feb 14, 2014 8:03 pm

Re: copy host memory into an array?

Postby pavanky » Mon Feb 24, 2014 1:19 am

Hi,

Code: Select all

array af_Data =  af::array(1,signalSize,af::c64);

// point device pointer
(cdouble*) d_signal = (cdouble*) af_Data.device<cdouble>();

//copy the host data in
cudaMemcpy(d_signal, host_array, sizeofData, cudamemcpyhosttodevice);



This can be simplified to

Code: Select all
array af_Data(1, signalSize, host_array, afHost); // Memcpy is done here
cdouble *d_signal = af_Data.device<cdouble>(); // Required data already here.
Pavan Yalamanchili,
ArrayFire
--
~ If it is not broken, you have not tried hard enough ~
User avatar
pavanky
Site Admin
 
Posts: 1123
Joined: Mon Mar 15, 2010 7:39 pm
Location: Atlanta, GA


Return to [archive-commercial] Programming & Development with ArrayFire

cron