Data Reshaping - 2022.1 English

AI Engine Kernel Coding Best Practices Guide (UG1079)

Document ID
UG1079
Release Date
2022-05-25
Version
2022.1 English

AI Engine API provides operations to change the location of the elements within a vector, to extract subvector from larger vector, or to combine the elements from two or more vectors.

The following APIs are provided to retrieve half of the vector by specific patterns.

aie::filter_even
Returns a vector of half the size by: out = { v[0:step], v[2*step:3*step], ... }
aie::filter_odd
Returns a vector of half the size by: out = { v[step:2*step], v[3*step:4*step], ... }
Note: The parameter step must be a power of two.
aie::vector<int32,8> result_e=aie::filter_even(xbuff, /*step=*/1);
aie::vector<int32,8> result_o=aie::filter_even(xbuff, /*step=*/4);

The following figures show how elements are chosen by aie::filter_even and aie::filter_odd.

Figure 1. aie::filter_even

Figure 2. aie::filter_odd

aie::select can be used to choose elements from two vectors (or a scalar and a vector) to form a new vector. aie::mask is used for specifying the element to choose.

aie::select
Choose elements by each bit of mask value: out = {mask[0] == 0? a[0] : b[0], …}
aie::vector<int32,8> vc=aie::select(va,vb,msk_value);//vc[i]=(mask_value[i]==0)?va[i]:vb[i]

AI Engine API provides following functions to shift vector elements by a specific number but maintain the vector size and element values.

aie::shuffle_down
Shift elements down by n: out = {v[n], v[n+1], …, v[Elems-1], undefined[0],…,undefined[n-1]}. Higher elements of output(out[n],out[n+1],…) are undefined. "Elems" is the vector size.
aie::shuffle_up
Shift elements up by n: out = {undefined[0],…,undefined[n-1],v[0], v[1], …}. Lower elements of output(out[0],…,out[n-1]) are undefined.
aie::shuffle_down_rotate
Rotate elements down by n: out = {v[n], v[n+1], …,v[Elems-1], v[0], …,v[n-1]}.
aie::shuffle_up_rotate
Rotate elements up by n: out = {v[Elems-n], …, v[Elems-1], v[0], …,v[n-1]}.
aie::shuffle_down_fill
Shift elements down by n and fill with elements from a second vector: out = {v[n], v[n+1], …, v[Elems-1], fill[0],…,fill[n-1]}. Higher elements of output(out[n],out[n+1],…) are filled with elements from second vector "fill"(fill[0],…,fill[n-1]).
aie::shuffle_up_fill
Shift elements up by n and fill with elements from a second vector: out = {fill[Elems-n],…,fill[Elems-1],v[0], v[1], …}. Lower elements of output(out[0],…,out[n-1]) are filled with elements from second vector "fill"(fill[Elems-n],…,fill[Elems-1]).
aie::vector<int32,8> v,fill;
//v_d[0:4]=v[3:7], (v_d[5],v_d[6],v_d[7] are undefined) 
auto v_d=aie::shuffle_down(v,3);
//v_u[3:7]=v[0:4], (v_u[0],v_u[1],v_u[2] are undefined) 
auto v_u=aie::shuffle_up(v,3);
auto vd_r=aie::shuffle_down_rotate(v,3);//vd_r[0:4]=v[3:7],vd_r[5:7]=v[0:2] 
auto vu_r=aie::shuffle_up_rotate(v,3);//vu_r[3:7]=v[0:4],vu_r[0:2]=v[5:7]
//v_d_fill[0:4]=v[3:7], v_d_fill[5:7]=fill[0:2]
auto v_d_fill=aie::shuffle_down_fill(v,fill,3);
//v_u_fill[3:7]=v[0:4], v_u_fill[0:2]=fill[5:7]
auto v_u_fill=aie::shuffle_up_fill(v,fill,3);

A vector can be reversed by:

aie::reverse
Reverse elements by: out = {v[Elems-1], …, v[1], v[0]}
aie::vector<int32,8> v_rev=aie::reverse(v,3);//v_rev[0:7]=v[7:0]

AI Engine API provides functions to shuffle two input vectors and combine them into the larger output vectors. The two vectors must be the same type and size. The return type is std::pair.

aie::interleave_zip
Select and combine two vectors by this pattern: out = { v1[0:step], v2[0:step], v1[step:2*step], v2[step:2*step], ... }
aie::inerleave_unzip
Select and combine two vectors by this pattern: out = { v1[0:step], v1[2*step:3*step], ..., v2[0:step], v2[2*step:3*step], ..., v1[step:2*step], v1[3*step:4*step], ..., v2[step:2*step], v2[3*step:4*step], ... }
Note: The parameter step must be a power of two.

The following example takes two vectors with reals in rva and imaginary in rvb (with type aie::vector<int32,8>) and creates a new complex vector. It also shows how to extract real and imaginary parts back and compare them with the original values.

aie::vector<int32,8> rva,rvb;
auto rv=aie::interleave_zip(rva,rvb,/*step*/1);
aie::vector<cint32,8> cv=aie::concat(rv.first.cast_to<cint32>(),rv.second.cast_to<cint32>());

auto [uva,uvb]=aie::interleave_unzip(rv.first,rv.second,/*step*/1);
bool ret=aie::equal(rva,uva) && aie::equal(rvb,uvb);//return true