Improve compilation speed by taking advantage of memoization#79
Improve compilation speed by taking advantage of memoization#79jonathanpoelen wants to merge 29 commits intoboostorg:developfrom
Conversation
477063d to
7f478ea
Compare
|
@pdimov would you be able to take a look, please? |
|
If you use |
7f478ea to
fc80d4a
Compare
|
This looks good to me. I can only wonder why I failed to look at it two years ago when you submitted it originally; it probably came in an inopportune time when I was too busy. I see a couple more things. It looks like you started to also optimize Also, in the two cases where the The 1.90 beta cutoff is the day after tomorrow, so I won't be able to merge this now, but to make sure I don't drop the ball again (sorry), please remind me after 1.90 is released. And thank you for this work. |
I went back to msvc because it wasn't working: 87719f6. However, after two years, the logs are no longer available.
Done.
I will try to remember :) |
|
I took the opportunity to go over what I had missed and use a gcc builtin for
|
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.66s - 206316K | 0:01.77s - 246832K |
| after | 0:00.63s - 192944K | 0:01.76s - 245956K |
template<class I> using test
= mp_nth_element<mp_iota_c<I::value+1>, I, mp_less>;
using r1 = mp_transform<test, mp_iota_c<30>>;mp_map_find_impl workaround (GCC)
| compiler | gcc-15 |
|---|---|
| before | 0:01.65s - 381364K |
| after | 0:00.99s - 213064K |
template<class L, class M = mp_transform<mp_list, L>>
struct f { template<class I> using g = mp_map_find<M, I>; };
template<class I, class L = mp_iota<I>> using test
= mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<50>>;mp_transform with 5 lists or more
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.21s - 80328K | 0:00.29s - 117756K |
| after | 0:00.20s - 77408K | 0:00.29s - 117468K |
template<class I, class L = mp_iota<I>> using test
= mp_transform<mp_list, L, L, L, L, L, L, L, L>;
using r1 = mp_transform<test, mp_iota_c<50>>;mp_fill
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.15s - 60740K | 0:00.14s - 94144K |
| after | 0:00.10s - 43504K | 0:00.14s - 94188K |
template<class I, class L = mp_iota<I>> using test
= mp_fill<L, int>;
using r1 = mp_transform<test, mp_iota_c<100>>;mp_replace_if
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.23s - 76088K | 0:00.37s - 116984K |
| after | 0:00.22s - 75348K | 0:00.35s - 114952K |
template<class> using pred = mp_false;
template<class I, class L = mp_iota<I>> using test
= mp_replace_if<L, pred, I>;
using r1 = mp_transform<test, mp_iota_c<120>>;mp_replace
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.30s - 90020K | 0:00.48s - 129272K |
| after | 0:00.29s - 89428K | 0:00.46s - 126580K |
template<class I, class L = mp_iota<I>> using test
= mp_replace<L, I, I>;
using r1 = mp_transform<test, mp_iota_c<120>>;mp_remove
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.32s - 91276K | 0:00.69s - 156512K |
| after | 0:00.31s - 90684K | 0:00.67s - 157560K |
template<class I, class L = mp_iota<I>> using test
= mp_remove<L, I>;
using r1 = mp_transform<test, mp_iota_c<120>>;mp_sliding_fold
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.23s - 79084K | 0:00.48s - 135100K |
| after | 0:00.22s - 77748K | 0:00.46s - 132436K |
template<class I, class L = mp_iota<I>> using test
= mp_list<
mp_sliding_fold<L, mp_int<2>, mp_plus>,
mp_sliding_fold<L, mp_int<2>, mp_max>
>;
using r1 = mp_transform<test, mp_iota_c<50>>;mp_copy_if
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.21s - 65820K | 0:00.51s - 138048K |
| after | 0:00.21s - 65428K | 0:00.49s - 138540K |
template<class> using pred = mp_false;
template<class I, class L = mp_iota<I>> using test
= mp_copy_if<L, pred>;
using r1 = mp_transform<test, mp_iota_c<120>>;mp_remove_if
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.21s - 67308K | 0:00.51s - 137744K |
| after | 0:00.21s - 66956K | 0:00.49s - 138492K |
template<class> using pred = mp_true;
template<class I, class L = mp_iota<I>> using test
= mp_remove_if<L, pred>;
using r1 = mp_transform<test, mp_iota_c<120>>;mp_map_replace
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.39s - 114524K | 0:00.66s - 155888K |
| after | 0:00.38s - 114140K | 0:00.64s - 155184K |
template<class I, class L = mp_transform<mp_list, mp_iota<I>>> using test
= mp_map_replace<L, mp_list<I,I>>;
using r1 = mp_transform<test, mp_iota_c<120>>;integer_sequence with gcc
Use the __integer_pack builtin
| compiler | gcc-15 |
|---|---|
| before | 0:00.14s - 47284K |
| after | 0:00.07s - 37572K |
template<class I> using test
= make_integer_sequence<int, I::value>;
using r1 = mp_transform<test, mp_iota_c<200>>;integer_sequence when no builtin is available
The probability that this code will be used is very low since msvc and clang-based compilers use __make_integer_seq and gcc uses __integer_pack. But it is shorter and eliminates the concatenation phase.
| compiler | gcc-15 | clang-20 |
|---|---|---|
| before | 0:00.14s - 47220K | 0:00.23s - 107632K |
| after | 0:00.10s - 40944K | 0:00.15s - 95144K |
template<class I> using test
= make_integer_sequence<int, I::value>;
using r1 = mp_transform<test, mp_iota_c<200>>;…emoization) compiler | gcc-12 | clang-15 before | 0:00.13s - 60432K | 0:00.16s - 100956K after | 0:00.11s - 47300K | 0:00.16s - 100484K ```cpp using namespace boost::mp11; template<class T> using p = mp_bool<T::value & 1>; template<class T> using f = mp_size_t<T::value + 1>; template<class I> using test = mp_transform_if<p, f, mp_iota<I>>; using r1 = mp_transform<test, mp_iota_c<50>>; ```
…tion) compiler | gcc-12 | clang-15 before | 0:00.16s - 72460K | 0:00.16s - 102068K after | 0:00.14s - 61884K | 0:00.16s - 101828K ```cpp using namespace boost::mp11; template<class T> using p = mp_bool<T::value & 1>; template<class I> using test = mp_filter<p, mp_iota<I>>; using r1 = mp_transform<test, mp_iota_c<50>>; ```
compiler | gcc-12 | clang-15
before | 0:00.48s - 192464K | 0:00.48s - 154480K
after | 0:00.43s - 172472K | 0:00.46s - 150404K
```cpp
template<class L> struct f { template<class I> using g = mp_drop<L, I>; };
template<class I, class L = mp_iota<I>> using test = mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<50>>;
```
compiler | gcc-12 | clang-15 before | 0:00.46s - 198848K | 0:00.49s - 132632K after | 0:00.42s - 183384K | 0:00.48s - 131748K ```cpp using namespace boost::mp11; template<class I> using test = mp_sort<mp_iota<I>, mp_less>; using r1 = mp_transform<test, mp_iota_c<25>>; ```
…oization) compiler | gcc-12 | clang-15 before | 0:00.34s - 134428K | 0:00.33s - 124720K after | 0:00.29s - 116920K | 0:00.32s - 122568K ```cpp using namespace boost::mp11; template<class I> using f = mp_replace_at<mp_iota<I>, I, void>; template<class I> using test = mp_transform<f, mp_iota<I>>; using r1 = mp_transform<test, mp_iota_c<50>>; ```
…ization) compiler | gcc-12 | clang-15 before | 0:01.35s - 538732K | 0:00.65s - 203924K after | 0:01.02s - 396032K | 0:00.65s - 203080K ```cpp using namespace boost::mp11; template<class I> using test = mp_power_set<mp_iota<I>>; using r1 = mp_transform<test, mp_iota_c<15>>; ```
…zation)
compiler | gcc-12 | clang-15
before | 0:00.29s - 128600K | 0:00.25s - 120604K
after | 0:00.22s - 99908K | 0:00.23s - 116084K
```cpp
using namespace boost::mp11;
template<class L, class M = mp_transform<mp_list, L>>
struct f { template<class I> using g = mp_map_find<M, I>; };
template<class I, class L = mp_iota<I>> using test
= mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<50>>;
```
…oization)
compiler | gcc-12 | clang-15
before | 0:00.73s - 270224K | 0:00.54s - 156112K
after | 0:00.19s - 85004K | 0:00.29s - 119232K
```cpp
using namespace boost::mp11;
template<class L, class M = mp_transform<mp_list, L>>
struct f { template<class I> using g = mp_map_update<M, mp_list<I>, mp_list>; };
template<class I, class L = mp_iota<I>> using test
= mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<20>>;
```
…ization)
compiler | gcc-12 | clang-15
before | 0:00.52s - 197128K | 0:00.44s - 140780K
after | 0:00.47s - 183968K | 0:00.43s - 139336K
```cpp
using namespace boost::mp11;
template<class L, class M = mp_transform<mp_list, L>>
struct f { template<class I> using g = mp_map_erase<M, I>; };
template<class I, class L = mp_iota<I>> using test
= mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<30>>;
```
compiler | gcc-12 | clang-15
before | 0:00.46s - 187160K | 0:00.38s - 129104K
after | 0:00.21s - 80236K | 0:00.33s - 123644K
```cpp
using namespace boost::mp11;
template<class L, class M = mp_transform<mp_list, L>>
struct f { template<class I> using g = mp_map_replace<M, mp_list<I, I>>; };
template<class I, class L = mp_iota<I>> using test
= mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<30>>;
```
compiler | gcc-15 | clang-20 before | 0:00.66s - 206316K | 0:01.77s - 246832K after | 0:00.63s - 192944K | 0:01.76s - 245956K ```cpp template<class I> using test = mp_nth_element<mp_iota_c<I::value+1>, I, mp_less>; using r1 = mp_transform<test, mp_iota_c<30>>; ```
compiler | gcc-15
before | 0:01.65s - 381364K
after | 0:00.99s - 213064K
```cpp
template<class L, class M = mp_transform<mp_list, L>>
struct f { template<class I> using g = mp_map_find<M, I>; };
template<class I, class L = mp_iota<I>> using test
= mp_transform<f<L>::template g, L>;
using r1 = mp_transform<test, mp_iota_c<50>>;
```
compiler | gcc-15 | clang-20 before | 0:00.21s - 80328K | 0:00.29s - 117756K after | 0:00.20s - 77408K | 0:00.29s - 117468K ```cpp template<class I, class L = mp_iota<I>> using test = mp_transform<mp_list, L, L, L, L, L, L, L, L>; using r1 = mp_transform<test, mp_iota_c<50>>; ```
compiler | gcc-15 | clang-20 before | 0:00.15s - 60740K | 0:00.14s - 94144K after | 0:00.10s - 43504K | 0:00.14s - 94188K ```cpp template<class I, class L = mp_iota<I>> using test = mp_fill<L, int>; using r1 = mp_transform<test, mp_iota_c<100>>; ```
compiler | gcc-15 | clang-20 before | 0:00.23s - 76088K | 0:00.37s - 116984K after | 0:00.22s - 75348K | 0:00.35s - 114952K ```cpp template<class> using pred = mp_false; template<class I, class L = mp_iota<I>> using test = mp_replace_if<L, pred, I>; using r1 = mp_transform<test, mp_iota_c<120>>; ```
compiler | gcc-15 | clang-20 before | 0:00.30s - 90020K | 0:00.48s - 129272K after | 0:00.29s - 89428K | 0:00.46s - 126580K ```cpp template<class I, class L = mp_iota<I>> using test = mp_replace<L, I, I>; using r1 = mp_transform<test, mp_iota_c<120>>; ```
compiler | gcc-15 | clang-20 before | 0:00.32s - 91276K | 0:00.69s - 156512K after | 0:00.31s - 90684K | 0:00.67s - 157560K ```cpp template<class> using pred = mp_true; template<class I, class L = mp_iota<I>> using test = mp_remove<L, I>; using r1 = mp_transform<test, mp_iota_c<120>>; ```
compiler | gcc-15 | clang-20
before | 0:00.23s - 79084K | 0:00.48s - 135100K
after | 0:00.22s - 77748K | 0:00.46s - 132436K
```cpp
template<class I, class L = mp_iota<I>> using test
= mp_list<
mp_sliding_fold<L, mp_int<2>, mp_plus>,
mp_sliding_fold<L, mp_int<2>, mp_max>
>;
using r1 = mp_transform<test, mp_iota_c<50>>;
```
compiler | gcc-15 | clang-20 before | 0:00.21s - 65820K | 0:00.51s - 138048K after | 0:00.21s - 65428K | 0:00.49s - 138540K ```cpp template<class> using pred = mp_false; template<class I, class L = mp_iota<I>> using test = mp_copy_if<L, pred>; using r1 = mp_transform<test, mp_iota_c<120>>; ```
compiler | gcc-15 | clang-20 before | 0:00.21s - 67308K | 0:00.51s - 137744K after | 0:00.21s - 66956K | 0:00.49s - 138492K ```cpp template<class> using pred = mp_true; template<class I, class L = mp_iota<I>> using test = mp_remove_if<L, pred>; using r1 = mp_transform<test, mp_iota_c<120>>; ```
compiler | gcc-15 | clang-20 before | 0:00.39s - 114524K | 0:00.66s - 155888K after | 0:00.38s - 114140K | 0:00.64s - 155184K ```cpp template<class I, class L = mp_transform<mp_list, mp_iota<I>>> using test = mp_map_replace<L, mp_list<I,I>>; using r1 = mp_transform<test, mp_iota_c<120>>; ```
Use the `__integer_pack` builtin compiler | gcc-15 before | 0:00.14s - 47284K after | 0:00.07s - 37572K ```cpp template<class I> using test = make_integer_sequence<int, I::value>; using r1 = mp_transform<test, mp_iota_c<200>>; ```
61c0251 to
b0b9c4e
Compare
compiler | gcc-15 | clang-20 before | 0:00.14s - 47220K | 0:00.23s - 107632K after | 0:00.10s - 40944K | 0:00.15s - 95144K ```cpp template<class I> using test = make_integer_sequence<int, I::value>; using r1 = mp_transform<test, mp_iota_c<200>>; ```
b0b9c4e to
4b54d24
Compare
|
@pdimov A quick reminder for this PR. |
I put in bulk the benchmarks and tests that can be found in each commit (issue #77)
(result of
/usr/bin/time --format='%Es - %MK' $compiler ...)mp_transform_ifmp_filtermp_dropmp_sortmp_replace_atmp_power_setmp_map_findmp_map_updatemp_map_erasemp_map_replace