github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/time_series_aggregate.h (about)

     1  //  Copyright (c) 2017-2018 Uber Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #ifndef QUERY_TIME_SERIES_AGGREGATE_H_
    16  #define QUERY_TIME_SERIES_AGGREGATE_H_
    17  
    18  #include <stdbool.h>
    19  #include <stddef.h>
    20  #include <stdint.h>
    21  #include "../cgoutils/utils.h"
    22  
    23  
    24  // some macro used for host or device compilation
    25  #ifdef RUN_ON_DEVICE
    26     #define SET_DEVICE(device) cudaSetDevice(device)
    27  #else
    28     #define SET_DEVICE(device)
    29  #endif
    30  
    31  // These C-style array limits are used to make the query structure as flat as
    32  // reasonably possible.
    33  enum {
    34    MAX_FOREIGN_TABLES = 7,
    35    MAX_COLUMNS_OF_A_TABLE = 32,
    36    MAX_DIMENSIONS = 8,
    37    MAX_DIMENSION_BYTES = 32,
    38    MAX_MEASURES = 32,
    39    MAX_INSTRUCTIONS = 1024,
    40    HASH_BUCKET_SIZE = 8,
    41    HASH_STASH_SIZE = 4,
    42    HLL_BITS = 14,
    43    HLL_DENSE_SIZE = 1 << HLL_BITS,
    44    HLL_DENSE_THRESHOLD = HLL_DENSE_SIZE / 4,
    45    // 16-byte, 8-byte, 4-byte, 2-byte, 1-byte
    46    NUM_DIM_WIDTH = 5,
    47  };
    48  
    49  // All aggregate functions supported in time series aggregate queries.
    50  enum AggregateFunction {
    51    AGGR_SUM_UNSIGNED = 1,
    52    AGGR_SUM_SIGNED = 2,
    53    AGGR_SUM_FLOAT = 3,
    54    AGGR_MIN_UNSIGNED = 4,
    55    AGGR_MIN_SIGNED = 5,
    56    AGGR_MIN_FLOAT = 6,
    57    AGGR_MAX_UNSIGNED = 7,
    58    AGGR_MAX_SIGNED = 8,
    59    AGGR_MAX_FLOAT = 9,
    60    AGGR_HLL = 10,
    61    AGGR_AVG_FLOAT = 11,
    62  };
    63  
    64  // All supported data type to covert golang vector to iterator.
    65  enum DataType {
    66    Bool,
    67    Int8,
    68    Uint8,
    69    Int16,
    70    Uint16,
    71    Int32,
    72    Uint32,
    73    Float32,
    74    Int64,
    75    Uint64,
    76    Float64,
    77    GeoPoint,
    78    UUID,
    79  };
    80  
    81  // All supported constant data types.
    82  enum ConstDataType {
    83    ConstInt,
    84    ConstFloat,
    85    ConstGeoPoint,
    86  };
    87  
    88  // All supported unary functor types.
    89  enum UnaryFunctorType {
    90    Negate,
    91    Not,
    92    BitwiseNot,
    93    IsNull,
    94    IsNotNull,
    95    Noop,
    96    GetWeekStart,
    97    GetMonthStart,
    98    GetQuarterStart,
    99    GetYearStart,
   100    GetDayOfMonth,
   101    GetDayOfYear,
   102    GetMonthOfYear,
   103    GetQuarterOfYear,
   104    GetHLLValue,
   105  };
   106  
   107  // All supported binary functor types.
   108  enum BinaryFunctorType {
   109    And,
   110    Or,
   111    Equal,
   112    NotEqual,
   113    LessThan,
   114    LessThanOrEqual,
   115    GreaterThan,
   116    GreaterThanOrEqual,
   117    Plus,
   118    Minus,
   119    Multiply,
   120    Divide,
   121    Mod,
   122    BitwiseAnd,
   123    BitwiseOr,
   124    BitwiseXor,
   125    Floor,
   126  };
   127  
   128  // RecordID
   129  typedef struct {
   130    int32_t batchID;
   131    uint32_t index;
   132  } RecordID;
   133  
   134  // HashIndex stores the HashIndex
   135  // For now we only support dimension table equal join
   136  // the hash index will not support event time
   137  typedef struct {
   138    uint8_t *buckets;
   139    uint32_t seeds[4];
   140  
   141    int keyBytes;
   142    int numHashes;
   143    int numBuckets;
   144  } CuckooHashIndex;
   145  
   146  // GeoPointT is the struct to represent a single geography point.
   147  typedef struct {
   148    float Lat;
   149    float Long;
   150  } GeoPointT;
   151  
   152  // UUIDT is the struct to represent a 16-bytes UUID.
   153  typedef struct {
   154    uint64_t p1;
   155    uint64_t p2;
   156  } UUIDT;
   157  
   158  typedef struct {
   159    bool HasDefault;
   160    union {
   161      bool BoolVal;
   162      int32_t Int32Val;
   163      uint32_t Uint32Val;
   164      float FloatVal;
   165      int64_t Int64Val;
   166      GeoPointT GeoPointVal;
   167      UUIDT UUIDVal;
   168    } Value;
   169  } DefaultValue;
   170  
   171  // VectorPartySlice stores the slice of each vector relevant to the query.
   172  // It should be supplied for leaf nodes of the AST tree.
   173  typedef struct {
   174    // Pointer points to memory allocated for this vp slice. We store counts,
   175    // nulls and values vector consecutively so that we can represent all
   176    // 3 pointers in the way like basePtr + 2 offsets.
   177    // If it's mode 0 vector, the BasePtr will be null.
   178    // If count vector does not present, the NullsOffset will be zero.
   179    // If null vector is not present, the ValuesOffset will be zero.
   180    uint8_t *BasePtr;
   181    uint32_t NullsOffset;
   182    uint32_t ValuesOffset;
   183    // Because of slicing and alignment, StartingIndex is not always 0.
   184    // StartingIndex will range from 0 to 7, with non-zero values only
   185    // used for bit-packed boolean values and nulls.
   186    uint8_t StartingIndex;
   187  
   188    // This is for converting the underlying pointer to appropriate pointer
   189    // type.
   190    enum DataType DataType;
   191    DefaultValue DefaultValue;
   192  
   193    uint32_t Length;
   194  } VectorPartySlice;
   195  
   196  // ScratchSpaceVector is the output vector for non-leaf non-root nodes and
   197  // input vector for non-leaf nodes that have at least one non-leaf child.
   198  typedef struct {
   199    uint8_t *Values;
   200    uint32_t NullsOffset;
   201    enum DataType DataType;
   202  } ScratchSpaceVector;
   203  
   204  // ConstantVector is the constant value in AST tree.
   205  typedef struct {
   206    // Value from the AST tree.
   207    union {
   208      int32_t IntVal;
   209      float FloatVal;
   210      GeoPointT GeoPointVal;
   211    } Value;
   212    // Whether this values is valid.
   213    bool IsValid;
   214    // A constant indicate const type can be used.
   215    enum ConstDataType DataType;
   216  } ConstantVector;
   217  
   218  // ForeignColumnVector stores all batches of vectors for the target column
   219  // and the record ids from hash lookup.
   220  // Note: foreign vector are only from
   221  // dimension tables and are unsorted columns from live batches.
   222  typedef struct {
   223    RecordID *RecordIDs;
   224    VectorPartySlice *Batches;
   225    int32_t BaseBatchID;
   226    int32_t NumBatches;
   227    int32_t NumRecordsInLastBatch;
   228    int16_t *const TimezoneLookup;
   229    int16_t TimezoneLookupSize;
   230    enum DataType DataType;
   231    DefaultValue DefaultValue;
   232  } ForeignColumnVector;
   233  
   234  // All supported input vector type.
   235  enum InputVectorType {
   236    VectorPartyInput,
   237    ScratchSpaceInput,
   238    ConstantInput,
   239    ForeignColumnInput
   240  };
   241  
   242  // InputVector is the vector used as input to transform and filter. Actual
   243  // type of input is decided by the type field.
   244  typedef struct {
   245    union {
   246      ConstantVector Constant;
   247      VectorPartySlice VP;
   248      ScratchSpaceVector ScratchSpace;
   249      ForeignColumnVector ForeignVP;
   250    } Vector;
   251    enum InputVectorType Type;
   252  } InputVector;
   253  
   254  // DimensionColumnVector stores the dimension vector byte array
   255  // DimensionColumnVector will be allocated together
   256  // The layout will be 4byte vectors followed by 2 byte vectors followed by 1
   257  // byte vectors and null vector (1 byte) Note: IndexVector is the indexVector of
   258  // dimension vector, not the index vector of the batch Sort and reduce will be
   259  // first done on IndexVector and than permutated to the output dimension vectors
   260  typedef struct {
   261    uint8_t *DimValues;
   262    uint64_t *HashValues;
   263    uint32_t *IndexVector;
   264    // length of single vector for each dimension
   265    // note: this does not necessarily equal to the length of the vector
   266    int VectorCapacity;
   267    uint8_t NumDimsPerDimWidth[NUM_DIM_WIDTH];
   268  } DimensionColumnVector;
   269  
   270  // DimensionOutputVector is used as the output vector of dimension
   271  // transformation for each dimension.
   272  typedef struct {
   273    uint8_t *DimValues;
   274    uint8_t *DimNulls;
   275    enum DataType DataType;
   276  } DimensionOutputVector;
   277  
   278  // MeasureOutputVector is used as output vector of measure transformation.
   279  // Right now we have one measure per query but we may have multiple measures
   280  // in future.
   281  typedef struct {
   282    // Where to write the values
   283    uint32_t *Values;
   284    enum DataType DataType;
   285    enum AggregateFunction AggFunc;
   286  } MeasureOutputVector;
   287  
   288  // All supported output vector type.
   289  enum OutputVectorType {
   290    ScratchSpaceOutput,
   291    MeasureOutput,
   292    DimensionOutput,
   293  };
   294  
   295  // OutputVector is the vector used as output of transform. Actual
   296  // type of input is decided by the type field.
   297  typedef struct {
   298    union {
   299      ScratchSpaceVector ScratchSpace;
   300      DimensionOutputVector Dimension;
   301      MeasureOutputVector Measure;
   302    } Vector;
   303    enum OutputVectorType Type;
   304  } OutputVector;
   305  
   306  /*
   307  // Batch stores all columns of the batch relevant to the query.
   308  //
   309  // Columns from different batches of the same table share the same order:
   310  //   1. Columns not from ArchivingSortColumns.
   311  //   2. Columns from ArchivingSortColumns in reverse order.
   312  typedef struct {
   313    VectorPartySlice Columns[MAX_COLUMNS_OF_A_TABLE];
   314  } Batch;
   315  
   316  // ForeignTable stores the data and join conditions of a table being joined.
   317  // A hash index on the equi-join columns is either maintained or created at
   318  // query time before the query executes.
   319  typedef struct {
   320    // Input data:
   321    Batch *batches;
   322    int32_t BaseBatchID;
   323    int32_t NumBatches;
   324  
   325    // Column metadata:
   326    int32_t NumColumns;
   327    uint16_t ValueBitsByColumn[MAX_COLUMNS_OF_A_TABLE];
   328  
   329    // TODO(shengyue): hash index
   330    CuckooHashIndex HashIndex;
   331  
   332    // Equi-join conditions:
   333    int32_t NumberOfEqualityPairs;
   334    // Index of each column in batches[x].Columns used in the equi-join
   335    // condition.
   336    uint8_t LocalColumns[MAX_COLUMNS_OF_A_TABLE];
   337    // Index of each remote column in the global column array used in the
   338    // equi-join condition. All columns from the main table are added to the
   339    // global column array, followed by all columns from the first foreign
   340    // table, followed by all columns from the second foreign table..
   341    // All remote columns must be present on the global column array by the time
   342    // this join happens; the values of which are used as the hash key to locate
   343    // the matching record on this table.
   344    uint8_t RemoteColumns[MAX_COLUMNS_OF_A_TABLE];
   345  } ForeignTable;
   346  
   347  // TimeSeriesAggregate defines the query, stores the input data from
   348  // foreign tables, and manages output buffers. Input data from the main table
   349  // are passed to Cuda separately to allow batch-based pipelining while reusing
   350  // the same query instance across multiple batches.
   351  typedef struct {
   352    // Foreign tables with input data and hash index:
   353    ForeignTable ForeignTables[MAX_FOREIGN_TABLES];
   354    int32_t NumForeignTables;
   355  
   356    // Column metadata for the main table:
   357    int32_t NumColumns;
   358    uint16_t ValueBitsByColumn[MAX_COLUMNS_OF_A_TABLE];
   359  
   360    // Query definition:
   361    int32_t NumDimensions;
   362    int32_t NumMeasures;
   363    // FilterInstsForUnsorted/ArchiveBatches produces 0 or 1 on top of the value
   364    // stack to indicate whether the record should be skipped or included for
   365    // all measures.
   366    uint32_t FilterInstsForLiveBatches[MAX_INSTRUCTIONS];
   367    uint32_t FilterInstsForArchiveBatches[MAX_INSTRUCTIONS];
   368    // DimMeasureInsts produces one uint32_t word for each dimension, followed
   369    // by one uint32_t word for each measure on top of the value stack.
   370    // It also produces one char for each dimension and measure on top of the
   371    // null stack to indicate whether they are valid (1) or null (0). A null
   372    // measure skips its aggregation. A null dimension is reported as null.
   373    uint32_t DimMeasureInsts[MAX_INSTRUCTIONS];
   374    // Actual word width (in bytes) of each dimension.
   375    uint8_t DimensionBytes[MAX_DIMENSIONS];
   376    // Total number of bytes of all dimensions.
   377    uint32_t TotalDimensionBytes;
   378    // Aggreate functions for each measure.
   379    enum AggregateFunction Aggregates[MAX_MEASURES];
   380  } TimeSeriesAggregate;
   381  */
   382  
   383  // GeoShape is the struct to represent a geofence shape. A single geoshape can
   384  // consists of multiple polygons including holes inside the polygons. Lats and
   385  // Longs vector stores the latitude and longitude values of each point of those
   386  // polygons.
   387  typedef struct {
   388    // Lats and Longs are stored in the format as
   389    //      [a1,a2,...an,a1,FLT_MAX,b1,bz,...bn]
   390    // where FLT_MAX denotes the beginning of next polygon.
   391    // We repeat the first vertex at end of each polygon, so the last line is
   392    // an-a1.
   393    float *Lats;
   394    float *Longs;
   395    // Number of coordinates including FLT_MAX placeholders  in the vector.
   396    uint16_t NumPoints;
   397  } GeoShape;
   398  
   399  // GeoShapeBatch
   400  typedef struct {
   401    // last
   402    uint8_t *LatLongs;
   403    // 1. first one byte stores total number of words(uint32_t) needed to
   404    // store predicate value (in or out of shape) of each shape per point
   405    // each shape will take 1 bit so every 32 shapes will take 1 word
   406    // 2. next three bytes stores the total number of points
   407    int32_t TotalNumPoints;
   408    uint8_t TotalWords;
   409  } GeoShapeBatch;
   410  
   411  // unaryTransform defines the C transform interface for golang to call.
   412  #ifdef __cplusplus
   413  extern "C" {
   414  #endif
   415  
   416  // InitIndexVector initialize index vector
   417  CGoCallResHandle InitIndexVector(uint32_t *indexVector,
   418                                   uint32_t start,
   419                                   int indexVectorLength,
   420                                   void *cudaStream,
   421                                   int device);
   422  
   423  // HashLookup looks up input values and stores results (record ids) into record
   424  // id vector
   425  CGoCallResHandle HashLookup(InputVector input,
   426                              RecordID *output,
   427                              uint32_t *indexVector,
   428                              int indexVectorLength,
   429                              uint32_t *baseCounts,
   430                              uint32_t startCount,
   431                              CuckooHashIndex hashIndex,
   432                              void *cudaStream,
   433                              int device);
   434  
   435  // UnaryTransform transforms an InputVector to output
   436  // OutputVector by applying UnaryFunctor to each of the element.
   437  // Output space should be preallocated by caller. Notice unaryTransform
   438  // should not accept a constant, this should be ensured by the query
   439  // compiler.
   440  CGoCallResHandle UnaryTransform(InputVector input,
   441                                  OutputVector output,
   442      // Will only be used at the leaf node and measure output.
   443                                  uint32_t *indexVector,
   444                                  int indexVectorLength,
   445      // Will only be used at the leaf node and measure output.
   446                                  uint32_t *baseCounts,
   447                                  uint32_t startCount,
   448                                  enum UnaryFunctorType functorType,
   449                                  void *cudaStream,
   450                                  int device);
   451  
   452  // UnaryFilter filters the index vector by applying the unary functor
   453  // on input and uses the result as the filter predicate. It returns the
   454  // index size after filtering. Caller is responsible for allocating
   455  // and initializing the index vector. Filter will be in-place so
   456  // no extra storage will be used.
   457  CGoCallResHandle UnaryFilter(InputVector input,
   458                               uint32_t *indexVector,
   459                               uint8_t *predicateVector,
   460                               int indexVectorLength,
   461      // Will only be used for foreign table column input
   462                               RecordID **recordIDVectors,
   463                               int numForeignTables,
   464      // Will only be used if this is a leaf node.
   465                               uint32_t *baseCounts,
   466                               uint32_t startCount,
   467                               enum UnaryFunctorType functorType,
   468                               void *cudaStream,
   469                               int device);
   470  
   471  // BinaryTransform applies BinaryFunctor on each pair of the elements in
   472  // lhs and rhs and writes the output to OutputVector. Output space should
   473  // be preallocated by caller. LHS and RHS cannot both be constant.
   474  CGoCallResHandle BinaryTransform(InputVector lhs,
   475                                   InputVector rhs,
   476                                   OutputVector output,
   477      // Will only be used at the leaf node and measure output.
   478                                   uint32_t *indexVector,
   479                                   int indexVectorLength,
   480      // Will only be used at the leaf node and measure output.
   481                                   uint32_t *baseCounts,
   482                                   uint32_t startCount,
   483                                   enum BinaryFunctorType functorType,
   484                                   void *cudaStream,
   485                                   int device);
   486  
   487  // BinaryFilter is the binary version of unaryFilter.
   488  CGoCallResHandle BinaryFilter(InputVector lhs,
   489                                InputVector rhs,
   490                                uint32_t *indexVector,
   491                                uint8_t *predicateVector,
   492                                int indexVectorLength,
   493      // Will only be used for foreign table column input
   494                                RecordID **recordIDVectors,
   495                                int numForeignTables,
   496      // Will only be used if this is a leaf node.
   497                                uint32_t *baseCounts,
   498                                uint32_t startCount,
   499                                enum BinaryFunctorType functorType,
   500                                void *cudaStream,
   501                                int device);
   502  
   503  // Sort performs a key-value sort to sort elements in keys and values in
   504  // ascending key order. Notice we don't need data type of the measure
   505  // values here since we only need to move the whole 4 bytes around
   506  // without any change.
   507  CGoCallResHandle Sort(DimensionColumnVector keys,
   508                        int length,
   509                        void *cudaStream,
   510                        int device);
   511  
   512  // Reduce reduces inputValues on inputKeys using the AggregateFunction and
   513  // write the unique keys to outputKeys and aggregation results to outputValues.
   514  // It returns number of unique keys as result also. Notice outputKeys and
   515  // outputValues should be preallocated by caller.
   516  CGoCallResHandle Reduce(DimensionColumnVector inputKeys,
   517                          uint8_t *inputValues,
   518                          DimensionColumnVector outputKeys,
   519                          uint8_t *outputValues,
   520                          int valueBytes,
   521                          int length,
   522                          enum AggregateFunction aggFunc,
   523                          void *cudaStream,
   524                          int device);
   525  
   526  /** Expand function is used to decompress the dimensions which are compressed
   527   through baseCounts, and append to existing outputKeys.
   528   @inputKeys input DimensionColumnVector
   529   @outputKeys output DimensionColumnVector
   530   @baseCounts count vector for first column
   531   @indexVector index vector of the dimension keys
   532   @indexVectorLen length of index vector will be used for the output, it should
   533    be less or equal to length of keys in inputKeys
   534   @outputOccupiedLen number of rows already in the outputKeys, as this will
   535    be append operation
   536  */
   537  CGoCallResHandle Expand(DimensionColumnVector inputKeys,
   538                          DimensionColumnVector outputKeys,
   539                          uint32_t *baseCounts,
   540                          uint32_t *indexVector,
   541                          int indexVectorLen,
   542                          int outputOccupiedLen,
   543                          void *cudaStream,
   544                          int device);
   545  
   546  // HyperLogLog is the interface to do hyperloglog in one cgo function call.
   547  // prevResultSize is to tell start position of keys and values of current batch.
   548  // hllVector (dense/sparse) will only be set when we allocate it for the last
   549  // batch. If it's the last batch. this function will return number of different
   550  // dim value combinations. Otherwise it returns the (previous result size +
   551  // number of unique hash values in current batch),
   552  // hllVectorSizePtr stores the size of hllVector
   553  // hllDimRegIDCount stores the num of reg_id per dim
   554  CGoCallResHandle HyperLogLog(DimensionColumnVector prevDimOut,
   555                               DimensionColumnVector curDimOut,
   556                               uint32_t *prevValuesOut,
   557                               uint32_t *curValuesOut,
   558                               int prevResultSize,
   559                               int curBatchSize,
   560                               bool isLastBatch,
   561                               uint8_t **hllVectorPtr,
   562                               size_t *hllVectorSizePtr,
   563                               uint16_t **hllDimRegIDCountPtr,
   564                               void *cudaStream,
   565                               int device);
   566  
   567  // GeoBatchIntersects is the interface to do geography intersections for all
   568  // geoshapes altogether. inOrOut represents whether we want to check geo points
   569  // are in the shape or not, 1 represents in and 0 represents not in.
   570  // outputPredicate will be used for filter.
   571  // Returns the filtered size otherwise returns the original size.
   572  CGoCallResHandle GeoBatchIntersects(
   573      GeoShapeBatch geoShapeBatch, InputVector points, uint32_t *indexVector,
   574      int indexVectorLength, uint32_t startCount, RecordID **recordIDVectors,
   575      int numForeignTables, uint32_t *outputPredicate, bool inOrOut,
   576      void *cudaStream, int device);
   577  
   578  // WriteGeoShapeDim is the interface to write the shape index to the dimension
   579  // output. This method should be called after GeoBatchIntersects removes all
   580  // non-intersecting rows. Note we need pass in the index vector length before
   581  // geo since outputPredicate has not done compaction yet.
   582  // Note:
   583  //   1. we assume that the geo join will be many-to-one join
   584  //   2. we only support IN operation for geo intersects join
   585  CGoCallResHandle WriteGeoShapeDim(
   586      int shapeTotalWords, DimensionOutputVector dimOut,
   587      int indexVectorLengthBeforeGeo, uint32_t *outputPredicate,
   588      void *cudaStream, int device);
   589  
   590  // BoostrapDevice will bootstrap the all gpu devices with approriate actions.
   591  // For now it will just initialize the constant memory.
   592  CGoCallResHandle BootstrapDevice();
   593  #ifdef __cplusplus
   594  }
   595  #endif
   596  
   597  #endif  // QUERY_TIME_SERIES_AGGREGATE_H_