Playing with ArrayFire: 05 First Meet Array (2)


Preface

In "Playing with ArrayFire: 04 First Know Array (1)", we have learned some specific uses of ArrayFire. In this article, we will continue to learn more uses of ArrayFire.


Six, index

    Like all functions in ArrayFire, indexing can also be executed in parallel on OpenCL/CUDA devices. Therefore, the index becomes part of the JIT operation and is done using parentheses instead of square brackets (ie as (0) instead of [0]). To index af:: array , you can use one or a combination of the following functions:

  • Integer scalar
  • seq() represents a linear sequence
  • end represents the last element of the dimension
  • span represents the entire dimension
  • row(i) or col(i) specify a single row/column
  • rows(first,last) or cols(first,last) specify the span of rows/columns

Seven, access the array memory on the host and device

     The memory in the array can be accessed using the host() and device() functions. The host function copies data from the device and makes it available in a C-style array on the host. Therefore, the developer manages the memory returned by the host. The device function returns a pointer/reference to the device memory for interoperability with external CUDA/OpenCL kernels. Since this memory belongs to ArrayFire, programmers should not try to release/release this pointer. For example, here is how we interact with OpenCL and CUDA:

    // Create an array consisting of 3 random numbers
    array a = randu(3, f32);
    // Copy an array on the device to the host:
    float * host_a = a.host<float>();
    // access the host data as a normal array
    printf("host_a[2] = %g\n", host_a[2]);  // last element
    // and free memory using delete:
    delete[] host_a;
    // Get access to the device memory for a CUDA kernel
    float * d_cuda = a.device<float>();    // no need to free this
    float value;
    cudaMemcpy(&value, d_cuda + 2, sizeof(float), cudaMemcpyDeviceToHost);
    printf("d_cuda[2] = %g\n", value);
    a.unlock(); // unlock to allow garbage collection if necessary
    // Because OpenCL uses references rather than pointers, accessing memory
    // is similar, but has a somewhat clunky syntax. For the C-API
    cl_mem d_opencl = (cl_mem) a.device<float>();
    // for the C++ API, you can just wrap this object into a cl::Buffer
    // after calling clRetainMemObject.

    ArrayFire also provides several auxiliary functions for creating af::array from OpenCL cl_mem references and cl::Buffer objects . For more information, please refer to the include/af/opencl.h file.     Finally, if you only want the first value of af::array , you can use the scalar() function to get it:

    array a = randu(3);
    float val = a.scalar<float>();
    printf("scalar value: %g\n", val)

Eight, bitwise operators

    In addition to supporting standard mathematical functions, arrays containing integral data types also support bitwise operators, including AND, OR, XOR:

    int h_A[] = {
    
    1, 1, 0, 0, 4, 0, 0, 2, 0};
    int h_B[] = {
    
    1, 0, 1, 0, 1, 0, 1, 1, 1};
    array A = array(3, 3, h_A), B = array(3, 3, h_B);
    af_print(A); af_print(B);
    array A_and_B = A & B; af_print(A_and_B);
    array  A_or_B = A | B; af_print(A_or_B);
    array A_xor_B = A ^ B; af_print(A_xor_B);

9. Use ArrayFire API in C and C++

     The ArrayFire API is packaged in a unified C/C++ header file. To use this library, just include the arrayfire.h header file and start coding!
    This is an example of using C API:

	#include <arrayfire.h>
	// Generate random data and sum and print the result
	int main(void)
	{
    
    
	    // generate random values
	    int n = 10000;
	    af_array a;
	    af_randu(&a, n);
	    // sum all the values
	    float result;
	    af_sum_all(&result, a, 0);
	    printf("sum: %g\n", result);
	    return 0;
	}

    This is an example of using C++ API:

	#include <arrayfire.h>
	// Generate random data, sum and print the result.
	int main(void)
	{
    
    
	    // Generate 10,000 random values
	    af::array a = af::randu(10000);
	    // Sum the values and copy the result to the CPU:
	    double sum = af::sum<float>(a);
	    printf("sum: %g\n", sum);
	    return 0;
	}

Guess you like

Origin blog.csdn.net/weixin_42467801/article/details/113612817