Example Usage - 2023.2 English

Vitis Libraries

Release Date
2023.2 English
// Take the short query above to demonstrate how to use L3 APIs.

// create GQE instance to handle card management
// with shell name, path to xclbin file to be loaded, operator combination
gqe::workshop wksp("xilinx_u50_gen3x16_xdma_5_202210_1", "./gqe_join.xclbin", gqe::WorkerFunctions::JOIN);

// Define input table schema, including attributes and size of each attribute's element.
// Also setup if enable rowid and validation bits or not.
// rowid is an auto generated attribute inside kernel.
// validation bits represent if valid for each input rows.
// Table O has 1 column, of type int64_t, attribute name is "o_rowid", rowID and validation bits enabled, attribute name is "o_rowid", "o_valid"
// Table L has 1 column, of type int64_t, attribute name is "l_rowid", rowID and validation bits enabled, attribute name is "l_rowid", "l_valid"
// Table C has 3 column, of type int64_t, attribute name is "c1", "c2", "c3", has no rowid and validation bits"
gqe::TableSection tab_o("Table O", {"o_orderkey"}, {sizeof(int64_t)}, 1, valid_o, "o_rowid", "o_valid");
gqe::TableSection tab_l("Table L", {"l_orderkey"}, {sizeof(int64_t)}, 1, valid_l, "l_rowid", "l_valid");
gqe::TableSection tab_c("Table C", {"c1", "c2", "c3"}, {sizeof(int64_t), sizeof(int64_t), sizeof(int64_t)}, 0, 0, "", "");

// After the schema of input table has been defined, add rows by section.
// Each section added to TableSection should contains exactly same number of columns in the exact same order of attribute.
// This only add pointers, which should been valid no later than this section's corresponding future is ready.
// tab_o_col0, tab_l_col0, tab_c_col0, tab_c_col1, tab_c_col2, tab_c_col3 are pointer to input and output memory
// tab_o_valid, tab_l_valid is the validation bits for table O and table L, represent filter result from previous processing, as input.
// tab_part_o_col0, tab_part_l_col0 are pointer to intermediate partition result.
tab_o.addSec(vector<char*>({(char*)tab_o_col0}), tab_o_valid, table_o_nrow);
tab_l.addSec(vector<char*>({(char*)tab_l_col0}), tab_l_valid, table_l_nrow);
tab_c.addSec(vector<char*>({(char*)tab_c_col0, (char*)tab_c_col1, (char*)tab_c_col2, (char*)tab_c_col3}, nullptr, table_c_nrow);
tab_part_o.addSec(vector<char*>({(char*)tab_part_o_col0}), nullptr, table_o_nrow * 2);
tab_part_l.addSec(vector<char*>({(char*)tab_part_l_col0}), nullptr, table_l_nrow * 2);

// intermeidiate result will be stored in "tab_part_o" and "tab_part_l".
// schema definition and adding section are similar
gqe::TableSection tab_part_o("Part O", {"o1", "o2", "o3"}, {sizeof(int64_t), sizeof(int64_t), sizeof(int64_t)}, 0, 0, "", "");
gqe::TableSection tab_part_l("Part L", {"l1", "l2", "l3"}, {sizeof(int64_t), sizeof(int64_t), sizeof(int64_t)}, 0, 0, "", "");
tab_part_o.addSec({((char*)tmp_o1), ((char*)tmp_o2), ((char*)tmp_o3)}, nullptr, d_part_o_nrow);
tab_part_l.addSec({((char*)tmp_l1), ((char*)tmp_l2), ((char*)tmp_l3)}, nullptr, d_part_l_nrow);

// Call GQE API to perform "filter + hash partition + hash join"
// This will merge the original execution plan tree into 1 operations.
// Table O is filtered with "o_rowid>0"
// No filter and only partition on table L.
// To support bigger input tableSection, GQE will also perform hash partition on Table O and Table L.
// Join table O and table L with "o_orderkey = l_orderkey", output 3 columns of l_orderkey, o_rowid and l_rowid.
// Join will return imediately
wksp.Join(&tab_o, "o_rowid>0", &tab_o_ready, &tab_part_o, &tab_l, "", &tab_l_ready, &tab_part_l,
      "o_orderkey = l_orderkey", "c1=l_orderkey,c2=o_rowid,c3=l_rowid", &tab_c, &tab_c_ready_promise,
      gqe::INNER_JOIN, smanual);

// get future from promise
std::future<size_t> tab_c_ready;
tab_c_ready = tab_c_ready_promise.get_future();
// wait for future

// release GQE