Skip to content

Commit

Permalink
improve heatmap render query performance
Browse files Browse the repository at this point in the history
  • Loading branch information
simoneves authored and andrewseidl committed May 6, 2020
1 parent c3bac98 commit dfd2bb0
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 11 deletions.
215 changes: 214 additions & 1 deletion QueryEngine/ExtensionFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,57 @@ float rect_pixel_bin_y(const double valy,
offset + rectheightf / 2.0f;
}

EXTENSION_NOINLINE
int32_t rect_pixel_bin_packed(const double valx,
const double minx,
const double maxx,
const double valy,
const double miny,
const double maxy,
const double rectwidth,
const double rectheight,
const double offsetx,
const double offsety,
const int32_t imgwidth,
const int32_t imgheight) {
const float imgwidthf = float(imgwidth);
const float rectwidthf = float(rectwidth);
double min = minx;
float offset = offsetx;
if (offset != 0) {
offset = fmodf(offset, rectwidthf);
if (offset > 0) {
offset -= rectwidthf;
}
min += offset * (maxx - minx) / imgwidthf;
}
float rx = float(int32_t(float((valx - min) / (maxx - min)) * (imgwidthf - offset) /
rectwidthf)) *
rectwidthf +
offset + rectwidthf / 2.0f;

const float imgheightf = float(imgheight);
const float rectheightf = rectheight;
min = miny;
offset = offsety;
if (offset != 0) {
offset = fmodf(offset, rectheightf);
if (offset > 0) {
offset -= rectheightf;
}
min += offset * (maxy - miny) / imgheightf;
}
float ry = float(int32_t(float((valy - min) / (maxy - min)) * (imgheightf - offset) /
rectheightf)) *
rectheightf +
offset + rectheightf / 2.0f;

// and pack as two 14.2 fixed-point values into 32bits
int32_t ux = static_cast<int32_t>(rx * 4.0f);
int32_t uy = static_cast<int32_t>(ry * 4.0f);
return (ux & 0x7FFF) | ((uy & 0x7FFF) << 16);
}

EXTENSION_NOINLINE
float reg_hex_horiz_pixel_bin_x(const double valx,
const double minx,
Expand Down Expand Up @@ -555,7 +606,7 @@ float reg_hex_horiz_pixel_bin_x(const double valx,
// Now convert the pixel position into a
// cube-coordinate system representation
const float hexsize = hexheightf / 2.0f;
const float cube_x = ((pix_x / sqrt3) - (pix_y / 3.0)) / hexsize;
const float cube_x = ((pix_x / sqrt3) - (pix_y / 3.0f)) / hexsize;
const float cube_z = (pix_y * 2.0f / 3.0f) / hexsize;
const float cube_y = -cube_x - cube_z;

Expand Down Expand Up @@ -652,6 +703,88 @@ float reg_hex_horiz_pixel_bin_y(const double valx,
return hexsize * 3.0f / 2.0f * rz + yoffset;
}

EXTENSION_NOINLINE
int32_t reg_hex_horiz_pixel_bin_packed(const double valx,
const double minx,
const double maxx,
const double valy,
const double miny,
const double maxy,
const double hexwidth,
const double hexheight,
const double offsetx,
const double offsety,
const int32_t imgwidth,
const int32_t imgheight) {
const float sqrt3 = 1.7320508075688772;
const float imgwidthf = float(imgwidth);
const float imgheightf = float(imgheight);
const float hexwidthf = float(hexwidth);
const float hexheightf = float(hexheight);

// expand the bounds of the data according
// to the input offsets. This is done because
// we also expand the image size according to the
// offsets because this algorithm layers the hexagon
// bins starting at the bottom left corner
double xmin = minx;
float xoffset = offsetx;
if (xoffset != 0) {
xoffset = fmodf(xoffset, hexwidthf);
if (xoffset > 0) {
xoffset -= hexwidthf;
}
xmin += xoffset * (maxx - xmin) / imgwidthf;
}

double ymin = miny;
float yoffset = offsety;
if (yoffset != 0) {
yoffset = fmodf(yoffset, 1.5f * hexheightf);
if (yoffset > 0) {
yoffset -= 1.5f * hexheightf;
}
ymin += yoffset * (maxy - ymin) / imgheightf;
}

// get the pixel position of the point
// assumes a linear scale here
// Rounds to the nearest pixel.
const float pix_x =
roundf((imgwidthf - xoffset) * float((valx - xmin) / (maxx - xmin)));
const float pix_y =
roundf((imgheightf - yoffset) * float((valy - ymin) / (maxy - ymin)));

// Now convert the pixel position into a
// cube-coordinate system representation
const float hexsize = hexheightf / 2.0f;
const float cube_x = ((pix_x / sqrt3) - (pix_y / 3.0f)) / hexsize;
const float cube_z = (pix_y * 2.0f / 3.0f) / hexsize;
const float cube_y = -cube_x - cube_z;

// need to round the cube coordinates above
float rx = round(cube_x);
float ry = round(cube_y);
float rz = round(cube_z);
const float x_diff = fabs(rx - cube_x);
const float y_diff = fabs(ry - cube_y);
const float z_diff = fabs(rz - cube_z);
if (x_diff > y_diff && x_diff > z_diff) {
rx = -ry - rz;
} else if (y_diff <= z_diff) {
rz = -rx - ry;
}

// now convert the cube/hex coord to pixel locations
float hx = hexsize * sqrt3 * (rx + rz / 2.0f) + xoffset;
float hy = hexsize * 3.0f / 2.0f * rz + yoffset;

// and pack as two 14.2 fixed-point values into 32bits
int32_t ux = static_cast<int32_t>(hx * 4.0f);
int32_t uy = static_cast<int32_t>(hy * 4.0f);
return (ux & 0x7FFF) | ((uy & 0x7FFF) << 16);
}

EXTENSION_NOINLINE
float reg_hex_vert_pixel_bin_x(const double valx,
const double minx,
Expand Down Expand Up @@ -802,6 +935,86 @@ float reg_hex_vert_pixel_bin_y(const double valx,
return hexsize * sqrt3 * (rz + rx / 2.0f) + yoffset;
}

EXTENSION_NOINLINE
int32_t reg_hex_vert_pixel_bin_packed(const double valx,
const double minx,
const double maxx,
const double valy,
const double miny,
const double maxy,
const double hexwidth,
const double hexheight,
const double offsetx,
const double offsety,
const int32_t imgwidth,
const int32_t imgheight) {
const float sqrt3 = 1.7320508075688772;
const float imgwidthf = float(imgwidth);
const float imgheightf = float(imgheight);
const float hexwidthf = float(hexwidth);
const float hexheightf = float(hexheight);

// expand the bounds of the data according
// to the input offsets. This is done because
// we also expand the image size according to the
// offsets because this algorithm layers the hexagon
// bins starting at the bottom left corner
double xmin = minx;
float xoffset = offsetx;
if (xoffset != 0) {
xoffset = fmodf(xoffset, 1.5f * hexwidthf);
if (xoffset > 0) {
xoffset -= 1.5f * hexwidthf;
}
xmin += xoffset * (maxx - xmin) / imgwidthf;
}

double ymin = miny;
float yoffset = offsety;
if (yoffset != 0) {
yoffset = fmodf(yoffset, hexheightf);
if (yoffset > 0) {
yoffset -= hexheightf;
}
ymin += yoffset * (maxy - ymin) / imgheightf;
}

// get the pixel position of the point
// assumes a linear scale here
// Rounds to the nearest pixel.
const float pix_x = roundf((imgwidthf - xoffset) * float(valx - xmin) / (maxx - xmin));
const float pix_y = roundf((imgheightf - yoffset) * float(valy - ymin) / (maxy - ymin));

// Now convert the pixel position into a
// cube-coordinate system representation
const float hexsize = hexwidthf / 2.0f;
const float cube_x = (pix_x * 2.0f / 3.0f) / hexsize;
const float cube_z = ((pix_y / sqrt3) - (pix_x / 3.0f)) / hexsize;
const float cube_y = -cube_x - cube_z;

// need to round the cube coordinates above
float rx = round(cube_x);
float ry = round(cube_y);
float rz = round(cube_z);
const float x_diff = fabs(rx - cube_x);
const float y_diff = fabs(ry - cube_y);
const float z_diff = fabs(rz - cube_z);
if (x_diff > y_diff && x_diff > z_diff) {
rx = -ry - rz;
} else if (y_diff <= z_diff) {
rz = -rx - ry;
}

// now convert the cube/hex coord to a pixel location
float hx = hexsize * 3.0f / 2.0f * rx + xoffset;
float hy = hexsize * sqrt3 * (rz + rx / 2.0f) + yoffset;

// and pack as two 14.2 fixed-point values into 32bits
int32_t ux = static_cast<int32_t>(hx * 4.0f);
int32_t uy = static_cast<int32_t>(hy * 4.0f);
return (ux & 0x7FFF) | ((uy & 0x7FFF) << 16);
}

EXTENSION_NOINLINE
double convert_meters_to_merc_pixel_width(const double meters,
const double lon,
Expand Down
10 changes: 10 additions & 0 deletions QueryEngine/RelAlgTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,16 @@ std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateFunction(
}
}
ret_ti.set_notnull(arguments_not_null);

// set encoding of certain Extension Function return values
if (func_resolve(rex_function->getName(),
"reg_hex_horiz_pixel_bin_packed"sv,
"reg_hex_vert_pixel_bin_packed"sv,
"rect_pixel_bin_packed"sv)) {
CHECK(ret_ti.get_type() == kINT);
ret_ti.set_compression(kENCODING_PACKED_PIXEL_COORD);
}

return makeExpr<Analyzer::FunctionOper>(ret_ti, rex_function->getName(), arg_expr_list);
}

Expand Down
2 changes: 2 additions & 0 deletions Shared/ThriftTypesConvert.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ inline TEncodingType::type encoding_to_thrift(const SQLTypeInfo& type_info) {
THRIFT_ENCODING_CASE(SPARSE)
THRIFT_ENCODING_CASE(GEOINT)
THRIFT_ENCODING_CASE(DATE_IN_DAYS)
THRIFT_ENCODING_CASE(PACKED_PIXEL_COORD)
default:
CHECK(false);
}
Expand All @@ -162,6 +163,7 @@ inline EncodingType thrift_to_encoding(const TEncodingType::type tEncodingType)
UNTHRIFT_ENCODING_CASE(SPARSE)
UNTHRIFT_ENCODING_CASE(GEOINT)
UNTHRIFT_ENCODING_CASE(DATE_IN_DAYS)
UNTHRIFT_ENCODING_CASE(PACKED_PIXEL_COORD)
default:
CHECK(false);
}
Expand Down
24 changes: 15 additions & 9 deletions Shared/sqltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,16 @@ union DataBlockPtr {

// must not change because these values persist in catalogs.
enum EncodingType {
kENCODING_NONE = 0, // no encoding
kENCODING_FIXED = 1, // Fixed-bit encoding
kENCODING_RL = 2, // Run Length encoding
kENCODING_DIFF = 3, // Differential encoding
kENCODING_DICT = 4, // Dictionary encoding
kENCODING_SPARSE = 5, // Null encoding for sparse columns
kENCODING_GEOINT = 6, // Encoding coordinates as intergers
kENCODING_DATE_IN_DAYS = 7, // Date encoding in days
kENCODING_LAST = 8
kENCODING_NONE = 0, // no encoding
kENCODING_FIXED = 1, // Fixed-bit encoding
kENCODING_RL = 2, // Run Length encoding
kENCODING_DIFF = 3, // Differential encoding
kENCODING_DICT = 4, // Dictionary encoding
kENCODING_SPARSE = 5, // Null encoding for sparse columns
kENCODING_GEOINT = 6, // Encoding coordinates as intergers
kENCODING_DATE_IN_DAYS = 7, // Date encoding in days
kENCODING_PACKED_PIXEL_COORD = 8, // Render Pixel Coordinate (packed 14.2+14.2)
kENCODING_LAST = 9
};

#define IS_INTEGER(T) \
Expand Down Expand Up @@ -426,6 +427,10 @@ class SQLTypeInfo {
return is_string() && compression == kENCODING_DICT;
}

inline bool is_packed_pixel_coord() const {
return type == kINT && compression == kENCODING_PACKED_PIXEL_COORD;
}

HOST DEVICE inline bool operator!=(const SQLTypeInfo& rhs) const {
return type != rhs.get_type() || subtype != rhs.get_subtype() ||
dimension != rhs.get_dimension() || scale != rhs.get_scale() ||
Expand Down Expand Up @@ -668,6 +673,7 @@ class SQLTypeInfo {
case kINT:
switch (compression) {
case kENCODING_NONE:
case kENCODING_PACKED_PIXEL_COORD:
return sizeof(int32_t);
case kENCODING_FIXED:
case kENCODING_SPARSE:
Expand Down
3 changes: 2 additions & 1 deletion common.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ enum TEncodingType {
DICT,
SPARSE,
GEOINT,
DATE_IN_DAYS
DATE_IN_DAYS,
PACKED_PIXEL_COORD
}

struct TTypeInfo {
Expand Down

0 comments on commit dfd2bb0

Please sign in to comment.