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_