ArrayFire로 플레이하기 : 04 First Know Array (1)


머리말

"Playing with ArrayFire : 03 The First ArrayFire Program"에서 우리는 첫 번째 ArrayFire 프로그램을 만들었지 만 ArrayFire의 사용법에 대해 깊이 이해하지 못했습니다.이 기사에서는 ArrayFire의 구체적인 사용법을 계속해서 배울 것입니다.


1. 배열에서 지원하는 데이터 유형

     ArrayFire는 배열 에서 함수와 수학적 연산을 수행 하는 일반적인 컨테이너 객체 제공합니다 . 배열은 다음 표에 나타낸 바와 같이, 많은 다른 기본 데이터 타입을 나타낼 수있다. 그리고 달리 지정되지 않는 한 배열의 기본 데이터 유형은 f32 (실제 단 정밀도 부동 소수점 숫자)입니다.

f32 실제 단 정밀도 부동 소수점 흙손
c32 복잡한 단 정밀도 부동 소수점 cfloat
f64 실수 배정 밀도 부동 소수점 더블
c64 복소 배정 밀도 부동 소수점 숫자 cdouble
b8 8 비트 부울 부울
s32 32 비트 부호있는 정수 int
u32 32 비트 부호없는 정수 서명되지 않은
u8 8 비트 부호없는 정수 부호없는 문자
s64 4 비트 부호있는 정수 intl
s16 6 비트 부호있는 정수 짧은
u16 16 비트 부호없는 정수 서명되지 않은 짧은

둘째, 배열 생성 및 채우기

     배열 은 장치 메모리 에 저장된 것을 나타냅니다 . 따라서 배열을 만들고 채우면 장치의 메모리가 소모 되며 배열 개체가 범위를 벗어날 때만 해제 될 수 있습니다 . 장치 메모리 할당은 비용이 많이들 수 있으므로 ArrayFire에는 가능할 때마다 장치 메모리를 재사용 하는 메모리 관리자 도 포함되어 있습니다.
    당신은 배열 형식을 사용해야하는 경우, 당신은 만들 수 있습니다 배열을 . 아래에서는 초기화되지 않은 값으로 1D, 2D 및 3D 배열을 만드는 방법을 보여줍니다.

    // Arrays may be created using the af::array constructor and dimensioned
    // as 1D, 2D, 3D; however, the values in these arrays will be undefined
    array undefined_1D(100);        // 1D array with 100 elements
    array undefined_2D(10, 100);    // 2D array of size 10 x 100
    array undefined_3D(10, 10, 10); // 3D array of size 10 x 10 x 10

    그러나 초기화되지 않은 메모리는 응용 프로그램에서 유용하지 않을 수 있습니다. ArrayFire는 상수, 균일 난수, 균일 정규 분포 번호 및 단위 행렬을 포함하여 미리 채워진 값을 포함하는 배열을 만드는 몇 가지 편리한 함수를 제공합니다.

    // Generate an array of size three filled with zeros.
    // If no data type is specified, ArrayFire defaults to f32.
    // The af::constant function generates the data on the device.
    array zeros      = constant(0, 3);
    // Generate a 1x4 array of uniformly distributed [0,1] random numbers
    // The af::randu function generates the data on the device.
    array rand1      = randu(1, 4);
    // Generate a 2x2 array (or matrix, if you prefer) of random numbers
    // sampled from a normal distribution.
    // The af::randn function generates data on the device.
    array rand2      = randn(2, 2);
    // Generate a 3x3 identity matrix. The data is generated on the device.
    array iden       = af::identity(3, 3);
    // Lastly, create a 2x1 array (column vector) of uniformly distributed
    // 32-bit complex numbers (c32 data type):
    array randcplx   = randu(2, 1, c32);

     어레이 는 호스트의 데이터로 채울 수도 있습니다. 예 :

    // Create a six-element array on the host
    float hA[] = {
    
    0, 1, 2, 3, 4, 5};
    // Which can be copied into an ArrayFire Array using the pointer copy
    // constructor. Here we copy the data into a 2x3 matrix:
    array A(2, 3, hA);
    // ArrayFire provides a convenince function for printing af::array
    // objects in case you wish to see how the data is stored:
    af_print(A);
    // This technique can also be used to populate an array with complex
    // data (stored in {
    
    {real, imaginary}, {real, imaginary},  ... } format
    // as found in C's complex.h and C++'s <complex>.
    // Below we create a 3x1 column vector of complex data values:
    array dB(3, 1, (cfloat*) hA); // 3x1 column vector of complex numbers
    af_print(dB);

     ArrayFire는 GPU 메모리에서 배열 초기화 도 지원합니다 . 예를 들어 CUDA를 사용하면 cudaMemcpy를 직접 호출하여 배열 을 채울 수 있습니다 .

    // Create an array on the host, copy it into an ArrayFire 2x3 ArrayFire array
    float host_ptr[] = {
    
    0,1,2,3,4,5};
    array a(2, 3, host_ptr);
    // Create a CUDA device pointer, populate it with data from the host
    float *device_ptr;
    cudaMalloc((void**)&device_ptr, 6*sizeof(float));
    cudaMemcpy(device_ptr, host_ptr, 6*sizeof(float), cudaMemcpyHostToDevice);
    // Convert the CUDA-allocated device memory into an ArrayFire array:
    array b(2,3, device_ptr, afDevice); // Note: afDevice (default: afHost)
    // Note that ArrayFire takes ownership over `device_ptr`, so memory will
    // be freed when `b` id destructed. Do not call cudaFree(device_ptr)!

     OpenCL에는 유사한 기능이 있습니다. ArrayFire를 CUDA 또는 OpenCL 코드와 혼합하려면 CUDA 상호 운용성 또는 OpenCL 상호 운용성 페이지에서 자세한 지침을 확인하는 것이 좋습니다.

셋, 배열의 내용, 크기 및 속성

     ArrayFire는 콘텐츠 인쇄, 차원 및 기타 특성 쿼리 기능을 포함하여 배열 의 특성 을 결정 하는 몇 가지 기능을 제공합니다 .
     af_print 함수는 생성 된 배열 또는 배열 과 관련된 모든 표현식 을 인쇄하는 데 사용할 수 있습니다 .

    // Generate two arrays
    array a = randu(2, 2);
    array b = constant(1, 2, 1);
    // Print them to the console using af_print
    af_print(a);
    af_print(b);
    // Print the results of an expression involving arrays:
    af_print(a.col(0) + b + .4);

     배열 의 차원은 dim4 객체에 의해 결정되거나 dims ()numdims () 함수를 사용하여 차원 직접 액세스하여 결정할 수 있습니다 .

    // Create a 4x5x2 array of uniformly distributed random numbers
    array a = randu(4,5,2);
    // Determine the number of dimensions using the numdims() function:
    printf("numdims(a)  %d\n",  a.numdims()); // 3
    // We can also find the size of the individual dimentions using either
    // the `dims` function:
    printf("dims = [%lld %lld]\n", a.dims(0), a.dims(1)); // 4,5
    // Or the elements of a af::dim4 object:
    dim4 dims = a.dims();
    printf("dims = [%lld %lld]\n", dims[0], dims[1]); // 4,5

    차원 외에도 배열 에는 기본 유형 및 크기 (바이트) 결정과 같은 다른 속성도 있습니다. 또한 배열 이 비어 있는지 , 실수 / 복소수, 행 / 열, 스칼라 또는 벡터 인지 확인할 수도 있습니다 .

    // Get the type stored in the array. This will be one of the many
    // `af_dtype`s presented above:
    printf("underlying type: %d\n", a.type());
    // Arrays also have several conveience functions to determine if
    // an Array contains complex or real values:
    printf("is complex? %d    is real? %d\n", a.iscomplex(), a.isreal());
    // if it is a column or row vector
    printf("is vector? %d  column? %d  row? %d\n", a.isvector(), a.iscolumn(), a.isrow());
    // and whether or not the array is empty and how much memory it takes on
    // the device:
    printf("empty? %d  total elements: %lld  bytes: %lu\n", a.isempty(), a.elements(), a.bytes());

넷째, 배열의 수학적 표현

     ArrayFire는 배열 을 사용하는 표현식 최소 CUDA / OpenCL 커널로 변환 할 수있는 스마트 JIT (Just-In-Time) 컴파일 엔진을 제공 합니다. 내용 의 대부분의 작업 어레이 , ArrayFire 함수 벡터 라이브러리와 유사하다. 즉, C에서 c [i] = a [i] + b [i]와 같은 요소 연산 은 c = a + b와 같이 인덱싱없이 더 간결하게 작성할 수 있습니다. arrays 와 관련된 여러 표현식 이있는 경우 ArrayFire의 JIT 엔진은이를 병합합니다. 이 "커널 융합"기술은 커널 호출 수를 줄일뿐만 아니라 더 중요한 것은 외부 전역 메모리 작업을 방지한다는 것입니다. JIT 함수는 C / C ++ 함수 경계를 확장하고 비 JIT 함수를 만나거나 코드가 명시 적으로 동기 작업을 호출 할 때만 종료됩니다.
     ArrayFire는 요소 조작을위한 수백 가지 기능을 제공합니다. 모든 표준 연산자 (예 : +,-, *, /)와 대부분의 초월 적 기능 (sin, cos, log, sqrt 등)을 지원합니다. 여기 몇 가지 예가 있어요.

    array R = randu(3, 3);
    af_print(constant(1, 3, 3) + af::complex(sin(R)));  // will be c32
    // rescale complex values to unit circle
    array a = randn(5, c32);
    af_print(a / abs(a));
    // calculate L2 norm of vectors
    array X = randn(3, 4);
    af_print(sqrt(sum(pow(X, 2))));     // norm of every column vector
    af_print(sqrt(sum(pow(X, 2), 0)));  // same as above
    af_print(sqrt(sum(pow(X, 2), 1)));  // norm of every row vector

다섯, 수학 상수

     ArrayFire에는 Pi, NaN 및 Inf와 같은 플랫폼 독립적 상수가 포함되어 있습니다. ArrayFire에 필요한 상수가없는 경우 af :: constant 배열 생성자를 사용하여 고유 한 상수를 만들 수 있습니다.
    상수는 ArrayFire의 모든 기능에서 사용할 수 있습니다. 아래에서는 요소 선택 및 수학 표현식에서의 사용을 보여줍니다.

    array A = randu(5,5);
    A(where(A > .5)) = af::NaN;
    array x = randu(10e6), y = randu(10e6);
    double pi_est = 4 * sum<float>(hypot(x,y) < 1) / 10e6;
    printf("estimation error: %g\n", fabs(Pi - pi_est));

    상수는 때때로 표준 헤더 파일의 매크로 정의와 충돌 할 수 있습니다. 이런 일이 발생하면 af :: 네임 스페이스를 사용하여 상수를 참조하십시오.


추천

출처blog.csdn.net/weixin_42467801/article/details/113574240