Choose efficient implementations

When implementing algorithms, prioritize both correctness and performance by selecting appropriate data structures, optimizing memory usage, and leveraging language features.

copy reviewer prompt

Prompt

Reviewer Prompt

When implementing algorithms, prioritize both correctness and performance by selecting appropriate data structures, optimizing memory usage, and leveraging language features.

Comparison functions

Implement proper three-way comparisons that handle equality cases correctly:

// INCORRECT: Returns only -1 or 1, missing 0 for equality
inline int WeightedDeltaCompare(const void* const a, const void* const b) {
  return (reinterpret_cast<const WeightedDelta*>(a)->delta -
          reinterpret_cast<const WeightedDelta*>(b)->delta) <= 0 ? 1 : -1;
}

// CORRECT: Returns -1, 0, or 1 for proper ordering
inline int WeightedDeltaCompare(const void* const a, const void* const b) {
    float delta_a = reinterpret_cast<const WeightedDelta*>(a)->delta;
    float delta_b = reinterpret_cast<const WeightedDelta*>(b)->delta;
    if (delta_a < delta_b) return -1;
    if (delta_a > delta_b) return 1;
    return 0;
}

Memory optimization

Defer memory allocation until needed to avoid unnecessary resource consumption:

// INEFFICIENT: Creates vector regardless of whether it will be used
std::vector<std::uint16_t> uint16_data;
if (GetDataType() != QNN_DATATYPE_SFIXED_POINT_16) {
  return;
}

// EFFICIENT: Only creates vector when it will be used
if (GetDataType() != QNN_DATATYPE_SFIXED_POINT_16) {
  return;
}
std::vector<std::uint16_t> uint16_data;

Vector initialization

Use std::iota for sequential initialization instead of manual loops:

// INEFFICIENT: Manual population of sequential values
std::vector<TypeParam> values;
for (int i = 0; i < 32768; i++) {
  values.push_back(i);
}

// EFFICIENT: Use std::iota for sequential initialization
std::vector<TypeParam> values(32768);
std::iota(values.begin(), values.end(), TypeParam(0));

Resource management

Use std::move when transferring collections to optimize performance:

// INEFFICIENT: Copying elements one by one
for (const auto& op_wrapper : op_wrappers) {
  graph_op_wrappers.emplace_back(op_wrapper);
}

// EFFICIENT: Moving entire collection at once
std::move(op_wrappers.begin(), op_wrappers.end(),
          std::back_inserter(graph_op_wrappers));

Mathematical correctness

Ensure mathematical algorithms handle edge cases and are implemented according to their proper definitions:

// INCORRECT: Wrong implementation of floormod
// floormod(x,y) = (x/y) - floor(x/y)

// CORRECT: Proper implementation with additional multiplication
// floormod(x,y) = ((x/y) - floor(x/y))*y

Numeric stability

Be vigilant about integer overflow, especially in calculations involving ranges or large numbers:

// VULNERABLE to overflow when limit-start is large
auto size_auto = Eigen::numext::ceil(Eigen::numext::abs((limit - start) / delta));

// SAFER approach to avoid overflow
auto size_auto = Eigen::numext::ceil(
    Eigen::numext::abs((limit / delta) - (start / delta)));

Source discussions