Open Quuxplusone opened 12 years ago
Attached evolved.cpp
(8049 bytes, application/octet-stream): metaprogramming torture test to compute prime numbers
The problem is that count_primes(16384) is being evaluated a large number of
times. We are apparently not storing the evaluated value for a non-type
template argument, and are instead re-evaluating it each time we need it.
(240x slower doesn't sound so bad when we're doing 16384x as much work...)
With this patch (and the include of <iostream> and main removed) clang -fsyntax-
only takes 47% less time to handle this code than g++ -fsyntax-only on my
machine:
@@ -227,11 +227,12 @@
template<unsigned N>
struct PrimeArrayReversed {
- PrimeArrayReverseImpl< typename GeneratePrimePack<count_primes(N)>::type>
const VALUE;
+ static constexpr unsigned Primes = count_primes(N);
+ PrimeArrayReverseImpl< typename GeneratePrimePack<Primes>::type> const
VALUE;
constexpr PrimeArrayReversed() : VALUE{} {}
- constexpr unsigned operator[](unsigned index) { return
VALUE.d_data[count_primes(N)-index]; }
+ constexpr unsigned operator[](unsigned index) { return VALUE.d_data[Primes-
index]; }
};
#define UNREVERSE_ARRAY
@@ -248,14 +249,14 @@
template<unsigned N>
struct PrimeArray {
- PrimeArrayImpl< N, typename GenerateLogPack<count_primes(N)>::type > const
VALUE;
+ PrimeArrayImpl< N, typename
GenerateLogPack<PrimeArrayReversed<N>::Primes>::type > const VALUE;
constexpr PrimeArray() : VALUE(PrimeArrayReversed<N>{}) {}
};
#else
template<unsigned N>
struct PrimeArray {
- PrimeArrayReverseImpl<typename GeneratePrimePack<count_primes(N)>::type>
const VALUE;
+ PrimeArrayReverseImpl<typename
GeneratePrimePack<PrimeArrayReversed<N>::Primes>::type> const VALUE;
constexpr PrimeArray() : VALUE{} {}
};
Tried this again today, and the gcc performance advantage is still present, but much lower - although I had to reduce the test bound from 2 << 14 to 2 << 10 to sit within the default recursion limits in the current compiler. I think this ticket can be closed as resolved, as we are no longer looking at multiple orders of magnitude difference.
evolved.cpp
(8049 bytes, application/octet-stream)