Compare commits

...
1 Commits
Author SHA1 Message Date
weaselbot d7de96ef94 Support building on ARM by providing scalar histogram fallback
The metrics histogram update code unconditionally included <immintrin.h>
and used __attribute__((target("avx"))) SSE/AVX intrinsics, which only
exist on x86-64. This prevented the project from compiling on ARM64.

Guard the x86-64 SIMD implementation and the <immintrin.h> include with
an architecture check, and add a portable scalar fallback for non-x86-64
platforms (e.g., ARM64). A thin wrapper function keeps the call sites
unchanged and preserves the AVX fast path on x86-64.

Closes #3
2026-06-26 10:49:53 -04:00
+24 -4
View File
@@ -22,7 +22,9 @@
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
#include <immintrin.h> #include <immintrin.h>
#endif
#include <simdutf.h> #include <simdutf.h>
#include "arena.hpp" #include "arena.hpp"
@@ -1398,8 +1400,10 @@ void Gauge::set(double x) {
Histogram::Histogram() = default; Histogram::Histogram() = default;
// Vectorized histogram bucket updates with mutex protection for consistency // Vectorized histogram bucket updates with mutex protection for consistency
// AVX-optimized implementation for high performance // AVX-optimized implementation for high performance on x86-64, scalar fallback
// on other architectures (e.g., ARM64).
#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
__attribute__((target("avx"))) static void __attribute__((target("avx"))) static void
update_histogram_buckets_simd(std::span<const double> thresholds, update_histogram_buckets_simd(std::span<const double> thresholds,
std::span<uint64_t> counts, double x, std::span<uint64_t> counts, double x,
@@ -1439,6 +1443,22 @@ update_histogram_buckets_simd(std::span<const double> thresholds,
} }
} }
} }
#endif
static void update_histogram_buckets(std::span<const double> thresholds,
std::span<uint64_t> counts, double x,
size_t start_idx) {
#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
update_histogram_buckets_simd(thresholds, counts, x, start_idx);
#else
const size_t size = thresholds.size();
for (size_t i = start_idx; i < size; ++i) {
if (x <= thresholds[i]) {
counts[i]++;
}
}
#endif
}
void Histogram::observe(double x) { void Histogram::observe(double x) {
assert(p->thresholds.size() == p->shared.bucket_counts.size()); assert(p->thresholds.size() == p->shared.bucket_counts.size());
@@ -1459,15 +1479,15 @@ void Histogram::observe(double x) {
} }
// Update shared directly // Update shared directly
update_histogram_buckets_simd(p->thresholds, p->shared.bucket_counts, x, 0); update_histogram_buckets(p->thresholds, p->shared.bucket_counts, x, 0);
p->shared.sum += x; p->shared.sum += x;
p->shared.observations++; p->shared.observations++;
p->mutex.unlock(); p->mutex.unlock();
} else { } else {
// Slow path: accumulate in pending (lock-free) // Slow path: accumulate in pending (lock-free)
update_histogram_buckets_simd(p->thresholds, p->pending.bucket_counts, x, update_histogram_buckets(p->thresholds, p->pending.bucket_counts, x,
0); 0);
p->pending.sum += x; p->pending.sum += x;
p->pending.observations++; p->pending.observations++;
} }