Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimized sort #202

Merged
merged 6 commits into from
Aug 23, 2016
Merged

Optimized sort #202

merged 6 commits into from
Aug 23, 2016

Conversation

jonathanpoelen
Copy link
Contributor

using list = brigand::sort<brigand::range<int, 0, SIZE>>;

gcc-5.4.0:

Size = 10 100 200 300 500
before 0.07s - 26M 0.42s - 148M 1.19s - 344M 2.28s - 609M 4.00s - 1011M
after 0.05s - 19M 0.16s - 45M 0.38s - 94M 0.66s - 152M 1.11s - 245M
gain 28% - 24% 61% - 69% 68% - 72% 71% - 75% 72% - 75%

clang-3.8.0:

Size = 10 100 200 300 500
before 0.09s - 40M 0.26s - 54M 0.66s - 95M 1.38s - 180M 2.49s - 321M
after 0.09s - 40M 0.21s - 50M 0.48s - 73M 0.78s - 101M 1.27s - 145M
gain 0% - 0% 19% - 6% 27% - 23% 43% - 43% 48% - 54%
using list = brigand::sort<brigand::reverse_range<int, SIZE, 0>>;

gcc-5.4.0:

Size = 10 100 200 300 500
before 0.05s - 21M 0.25s - 83M 0.46s - 152M 0.70s - 223M 1.37s - 375M
after 0.05s - 19M 0.14s - 40M 0.26s - 65M 0.39s - 93M 0.71s - 161M
gain 0% - 7% 43% - 51% 43% - 56% 44% - 58% 48% - 56%

clang-3.8.0:

Size = 10 100 200 300 500
before 0.08s - 40M 0.19s - 48M 0.34s - 63M 0.52s - 81M 0.98s - 129M
after 0.09s - 40M 0.19s - 49M 0.32s - 60M 0.47s - 73M 0.84s - 108M
gain -12% - -1% 0% - 0% 5% - 4% 9% - 8% 14% - 16%
using list = brigand::sort<
  brigand::transform<
    brigand::range<int, 0, SIZE>,
    brigand::bind<brigand::modulo, brigand::_1, std::integral_constant<int, 40>>
  >
>;

gcc-5.4.0:

Size = 10 100 200 300 500
before 0.07s - 27M 0.53s - 177M 1.66s - 469M 3.02s - 789M 5.89s - 1406M
after 0.05s - 21M 0.22s - 56M 0.54s - 121M 0.92s - 199M 1.90s - 341M
gain 28% - 23% 58% - 68% 67% - 74% 69% - 74% 67% - 75%

clang-3.8.0:

Size = 10 100 200 300 500
before 0.10s - 41M 0.33s - 60M 0.96s - 127M 1.76s - 217M 3.83s - 449M
after 0.10s - 41M 0.26s - 55M 0.60s - 87M 1.04s - 131M 1.81s - 204M
gain 0% - -1% 21% - 7% 37% - 31% 40% - 39% 52% - 54%
using list = brigand::sort<brigand::append<
  brigand::range<int, SIZE/2, SIZE>,
  brigand::range<int, 0, SIZE/2>
>>;

gcc-5.4.0:

Size = 10 100 200 300 500
before 0.07s - 25M 0.46s - 158M 1.11s - 328M 1.86s - 534M 3.38s - 903M
after 0.05s - 19M 0.17s - 45M 0.33s - 82M 0.63s - 139M 1.13s - 244M
gain 28% - 20% 63% - 71% 70% - 74% 66% - 73% 66% - 72%

clang-3.8.0:

Size = 10 100 200 300 500
before 0.09s - 40M 0.28s - 55M 0.61s - 86M 1.13s - 138M 2.02s - 245M
after 0.09s - 41M 0.21s - 51M 0.40s - 67M 0.71s - 101M 1.27s - 146M
gain 0% - 0% 25% - 8% 34% - 22% 37% - 27% 37% - 40%

```cpp
using list = brigand::sort<brigand::range<int, 0, SIZE>>;
```

gcc-5.4.0:

Size = |      10     |      50     |      100     |      200     |      300     |      500
------ | ----------- | ----------- | ------------ | ------------ | ------------ | ------------
before | 0.07s - 26M | 0.21s - 75M | 0.42s - 148M | 1.19s - 344M | 2.28s - 609M | 4.00s - 1011M
after  | 0.05s - 21M | 0.12s - 34M | 0.23s -  56M | 0.58s - 125M | 1.20s - 233M | 2.45s - 393M
gain   |  28%  - 20% |  42%  - 54% |  45%  -  61% |  51%  -  63% |  47%  -  61% |  38%  -  61%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.09s - 40M | 0.15s - 45M | 0.26s - 54M | 0.66s - 95M | 1.38s - 180M | 2.49s - 321M
after  | 0.09s - 41M | 0.15s - 45M | 0.25s - 54M | 0.64s - 94M | 1.32s - 178M | 2.42s - 317M
gain   |   0%  - -1% |   0%  -  0% |   3%  -  0% |   3%  -  0% |   4%  -   1% |   2%  -   1%

```cpp
using list = brigand::sort<brigand::reverse_range<int, SIZE, 0>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.05s - 21M | 0.13s - 49M | 0.25s - 83M | 0.46s - 152M | 0.70s - 223M | 1.37s - 375M
after  | 0.05s - 19M | 0.10s - 29M | 0.14s - 40M | 0.27s -  66M | 0.42s -  94M | 0.75s - 155M
gain   |   0%  -  6% |  23%  - 41% |  43%  - 50% |  41%  -  56% |  40%  -  57% |  45%  -  58%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |     300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ----------- | ------------
before | 0.08s - 40M | 0.13s - 44M | 0.19s - 48M | 0.34s - 63M | 0.52s - 81M | 0.98s - 129M
after  | 0.08s - 40M | 0.13s - 44M | 0.20s - 49M | 0.34s - 62M | 0.51s - 80M | 0.95s - 128M
gain   |   0%  - -1% |   0%  -  0% |  -5%  - -1% |   0%  -  0% |   1%  -  0% |   3%  -   1%

```cpp
using list = brigand::sort<
  brigand::transform<
    brigand::range<int, 0, SIZE>,
    brigand::bind<brigand::modulo, brigand::_1, std::integral_constant<int, 40>>
  >
>;
```

gcc-5.4.0:

Size = |      10     |      50     |      100     |      200     |      300     |      500
------ | ----------- | ----------- | ------------ | ------------ | ------------ | ------------
before | 0.07s - 27M | 0.22s - 81M | 0.53s - 177M | 1.66s - 469M | 3.02s - 789M | 5.89s - 1406M
after  | 0.07s - 21M | 0.13s - 38M | 0.28s -  69M | 0.86s - 175M | 1.78s - 298M | 3.63s - 559M
gain   |   0%  - 21% |  40%  - 53% |  47%  -  61% |  48%  -  62% |  41%  -  62% |  38%  -  60%

clang-3.8.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.10s - 41M | 0.17s - 47M | 0.33s - 60M | 0.96s - 127M | 1.76s - 217M | 3.83s - 449M
after  | 0.10s - 41M | 0.16s - 46M | 0.32s - 59M | 0.92s - 124M | 1.69s - 214M | 3.58s - 443M
gain   |   0%  -  0% |   5%  -  0% |   3%  -  2% |   4%  -   1% |   3%  -   1% |   6%  -   1%

```cpp
using list = brigand::sort<brigand::append<
  brigand::range<int, SIZE/2, SIZE>,
  brigand::range<int, 0, SIZE/2>
>>;
```

gcc-5.4.0:

Size = |      10     |      50     |      100     |      200     |      300     |      500
------ | ----------- | ----------- | ------------ | ------------ | ------------ | ------------
before | 0.07s - 25M | 0.22s - 81M | 0.46s - 158M | 1.11s - 328M | 1.86s - 534M | 3.38s - 1903M
after  | 0.05s - 20M | 0.13s - 36M | 0.23s -  59M | 0.52s - 116M | 0.96s - 195M | 1.98s - 332M
gain   |  28%  - 17% |  40%  - 54% |  50%  -  62% |  53%  -  64% |  48%  -  63% |  41%  -  63%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.09s - 40M | 0.16s - 46M | 0.28s - 55M | 0.61s - 86M | 1.13s - 138M | 2.02s - 245M
after  | 0.09s - 41M | 0.16s - 46M | 0.27s - 55M | 0.58s - 85M | 1.06s - 137M | 1.97s - 242M
gain   |   0%  - -1% |   0%  -  0% |   3%  -  0% |   4%  -  0% |   6%  -   0% |   2%  -   1%
```cpp
using list = brigand::sort<brigand::range<int, 0, SIZE>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.05s - 21M | 0.12s - 34M | 0.23s - 56M | 0.58s - 125M | 1.20s - 233M | 2.45s - 393M
after  | 0.06s - 21M | 0.12s - 34M | 0.23s - 56M | 0.58s - 125M | 1.22s - 242M | 2.03s - 351M
gain   | -20%  - -1% |   0%  -  0% |   0%  -  0% |   0%  -   0% |  -1%  -  -3% |  17%  -  10%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.09s - 41M | 0.15s - 45M | 0.25s - 54M | 0.64s - 94M | 1.32s - 178M | 2.42s - 317M
after  | 0.10s - 41M | 0.15s - 46M | 0.26s - 54M | 0.64s - 94M | 1.36s - 176M | 1.95s - 236M
gain   | -11%  -  0% |   0%  -  0% |  -4%  -  0% |   0%  -  0% |  -3%  -   1% |  19%  -  25%

```cpp
using list = brigand::sort<brigand::reverse_range<int, SIZE, 0>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |     200     |     300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ----------- | ------------
before | 0.05s - 19M | 0.10s - 29M | 0.14s - 40M | 0.27s - 66M | 0.42s - 94M | 0.75s - 155M
after  | 0.06s - 20M | 0.09s - 29M | 0.15s - 41M | 0.27s - 66M | 0.42s - 94M | 0.76s - 167M
gain   | -20%  - -1% |  10%  - -1% |  -7%  -  0% |   0%  -  0% |   0%  -  0% |  -1%  -  -7%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |     300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ----------- | ------------
before | 0.08s - 40M | 0.13s - 44M | 0.20s - 49M | 0.34s - 62M | 0.51s - 80M | 0.95s - 128M
after  | 0.09s - 41M | 0.13s - 44M | 0.19s - 49M | 0.34s - 63M | 0.49s - 78M | 0.89s - 118M
gain   | -12%  - -1% |   0%  -  0% |   5%  -  0% |   0%  -  0% |   3%  -  3% |   6%  -   7%

```cpp
using list = brigand::sort<
  brigand::transform<
    brigand::range<int, 0, SIZE>,
    brigand::bind<brigand::modulo, brigand::_1, std::integral_constant<int, 40>>
  >
>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.07s - 21M | 0.13s - 38M | 0.28s - 69M | 0.86s - 175M | 1.78s - 298M | 3.63s - 559M
after  | 0.06s - 22M | 0.13s - 38M | 0.29s - 69M | 0.87s - 175M | 1.44s - 278M | 2.66s - 459M
gain   |  14%  - -1% |   0%  -  0% |  -3%  -  0% |  -1%  -   0% |  19%  -   6% |  26%  -  17%

clang-3.8.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.10s - 41M | 0.16s - 46M | 0.32s - 59M | 0.92s - 124M | 1.69s - 214M | 3.58s - 443M
after  | 0.11s - 41M | 0.17s - 47M | 0.32s - 60M | 0.93s - 124M | 1.51s - 191M | 2.50s - 288M
gain   |  -9%  -  0% |  -6%  -  0% |   0%  - -1% |  -1%  -   0% |  10%  -  10% |  30%  -  35%

```cpp
using list = brigand::sort<brigand::append<
  brigand::range<int, SIZE/2, SIZE>,
  brigand::range<int, 0, SIZE/2>
>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.05s - 20M | 0.13s - 36M | 0.23s - 59M | 0.52s - 116M | 0.96s - 195M | 1.98s - 332M
after  | 0.06s - 21M | 0.13s - 37M | 0.24s - 60M | 0.53s - 116M | 0.91s - 191M | 1.85s - 325M
gain   | -20%  - -1% |   0%  - -1% |  -4%  -  0% |  -1%  -   0% |   5%  -   2% |   6%  -   2%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.09s - 41M | 0.16s - 46M | 0.27s - 55M | 0.58s - 85M | 1.06s - 137M | 1.97s - 242M
after  | 0.10s - 41M | 0.16s - 46M | 0.28s - 55M | 0.58s - 85M | 1.00s - 127M | 1.76s - 212M
gain   | -11%  -  0% |   0%  - -1% |  -3%  -  0% |   0%  -  0% |   5%  -   7% |  10%  -  12%
```cpp
using list = brigand::sort<brigand::range<int, 0, SIZE>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.06s - 21M | 0.12s - 34M | 0.23s - 56M | 0.58s - 125M | 1.22s - 242M | 2.03s - 351M
after  | 0.06s - 21M | 0.10s - 31M | 0.18s - 50M | 0.42s - 109M | 0.72s - 178M | 1.40s - 289M
gain   |   0%  -  0% |  16%  -  9% |  21%  - 10% |  27%  -  12% |  40%  -  26% |  31%  -  17%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.10s - 41M | 0.15s - 46M | 0.26s - 54M | 0.64s - 94M | 1.36s - 176M | 1.95s - 236M
after  | 0.10s - 41M | 0.14s - 45M | 0.23s - 53M | 0.53s - 80M | 0.88s - 114M | 1.46s - 166M
gain   |   0%  -  0% |   6%  -  0% |  11%  -  1% |  17%  - 15% |  35%  -  34% |  25%  -  29%

```cpp
using list = brigand::sort<brigand::reverse_range<int, SIZE, 0>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.06s - 20M | 0.09s - 29M | 0.15s - 41M | 0.27s - 66M | 0.42s -  94M | 0.76s - 167M
after  | 0.05s - 20M | 0.10s - 31M | 0.16s - 45M | 0.29s - 75M | 0.42s - 109M | 0.78s - 192M
gain   |  16%  - -4% | -11%  - -6% |  -6%  - 10% |  -7%  - 14% |   0%  - -16% |  -2%  - -14%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |     300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ----------- | ------------
before | 0.09s - 41M | 0.13s - 44M | 0.19s - 49M | 0.34s - 63M | 0.49s - 78M | 0.89s - 118M
after  | 0.09s - 41M | 0.14s - 45M | 0.21s - 51M | 0.36s - 64M | 0.54s - 80M | 0.96s - 121M
gain   |   0%  -  0% |  -7%  - -2% | -10%  - -3% |  -5%  - -2% | -10%  - -3% |  -7%  -  -2%

```cpp
using list = brigand::sort<
  brigand::transform<
    brigand::range<int, 0, SIZE>,
    brigand::bind<brigand::modulo, brigand::_1, std::integral_constant<int, 40>>
  >
>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.06s - 22M | 0.13s - 38M | 0.29s - 69M | 0.87s - 175M | 1.44s - 278M | 2.66s - 459M
after  | 0.06s - 22M | 0.11s - 36M | 0.23s - 63M | 0.59s - 141M | 1.01s - 238M | 2.06s - 411M
gain   |   0%  -  0% |  15%  -  5% |  20%  -  7% |  32%  -  19% |  29%  -  14% |  22%  -  10%

clang-3.8.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.11s - 41M | 0.17s - 47M | 0.32s - 60M | 0.93s - 124M | 1.51s - 191M | 2.50s - 288M
after  | 0.10s - 42M | 0.17s - 47M | 0.29s - 59M | 0.70s -  99M | 1.24s - 160M | 2.19s - 256M
gain   |   9%  - -1% |   0%  -  0% |   9%  -  0% |  24%  -  20% |  17%  -  16% |  12%  -  10%

```cpp
using list = brigand::sort<brigand::append<
  brigand::range<int, SIZE/2, SIZE>,
  brigand::range<int, 0, SIZE/2>
>>;
```

gcc-5.4.0:

Size = |      10     |      50     |     100     |      200     |      300     |      500
------ | ----------- | ----------- | ----------- | ------------ | ------------ | ------------
before | 0.06s - 21M | 0.13s - 37M | 0.24s - 60M | 0.53s - 116M | 0.91s - 191M | 1.85s - 325M
after  | 0.06s - 21M | 0.11s - 34M | 0.19s - 51M | 0.37s -  95M | 0.69s - 168M | 1.39s - 288M
gain   |   0%  -  0% |  15%  -  7% |  20%  - 14% |  30%  -  18% |  24%  -  11% |  24%  -  11%

clang-3.8.0:

Size = |      10     |      50     |     100     |     200     |      300     |      500
------ | ----------- | ----------- | ----------- | ----------- | ------------ | ------------
before | 0.10s - 41M | 0.16s - 46M | 0.28s - 55M | 0.58s - 85M | 1.00s - 127M | 1.76s - 212M
after  | 0.09s - 41M | 0.16s - 46M | 0.24s - 54M | 0.46s - 72M | 0.86s - 118M | 1.45s - 167M
gain   |  10%  -  0% |   0%  -  0% |  14%  -  3% |  20%  - 14% |  14%  -   7% |  17%  -  21%
@edouarda edouarda merged commit 43ca010 into edouarda:master Aug 23, 2016
@odinthenerd
Copy link
Contributor

Nice job! I think we can optimize even further by using the "universal fast track approach". still 500 elements in just over a second is amazing!

}

template<class Seq1, class Seq2, class Comp = less<_1,_2>>
using merge = append<clear<Seq1>, typename detail::merge_impl<clear<Seq1>, wrap<Seq1, list>, wrap<Seq2, list>, Comp>::type>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't you mean detail::merge_impl<list<>, wrap<Seq1, list>, wrap<Seq2, list>, Comp>::type here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rogue, he escaped.

@jonathanpoelen
Copy link
Contributor Author

I think we can optimize even further by using the "universal fast track approach".

Probably. I tried some tricks, but without results. I think tried 1 or 2 other things.
Next step, less than a second with 500 elements? :D

@jonathanpoelen
Copy link
Contributor Author

I just test again with the "universal fast track" by applying it directly on detail::apply:

        template <template<typename,typename> class F, typename T, typename U>
        struct apply<F<_1,_2>, list<T, U>> : F<T, U>
        {
        };

        template <template<typename,typename> class F, typename T, typename U>
        struct apply<F<_2,_1>, list<T, U>> : F<U, T>
        {
        };

gcc: ~+20%
clang: ~+6%

@odinthenerd
Copy link
Contributor

Yes under one second, the race is on ;) for kvasir I need 1000 elements to not crash and not be more than the default max instantiation depth

@ldionne
Copy link

ldionne commented Aug 24, 2016

Is this sort stable?

@odinthenerd
Copy link
Contributor

I think #208 is the last bug. I have been hammering it.

@jonathanpoelen
Copy link
Contributor Author

Is this sort stable?

No, but it could.

In the meantime.

template<class L, class Comp> using stable_sort
  = sort<L, not_<bind<apply, pin<Comp>, _2, _1>>>;

@edouarda
Copy link
Owner

@ldionne do you have any specific use case in mind for a stable sort? I'm curious.

@ldionne
Copy link

ldionne commented Aug 25, 2016

It's just that Hana's sort is documented as being stable, and I would love to steal Brigand's implementation.

@odinthenerd
Copy link
Contributor

sounds like we need to make it stable

@ldionne
Copy link

ldionne commented Aug 25, 2016

Well, if anything, it would be wiser to provide a stable_sort than to mandate the current sort to be stable; this way you don't lock yourself into a corner where you have to make your sort function stable (as I did).

@edouarda
Copy link
Owner

Got it, thanks.

@brunocodutra
Copy link

metal::sort is stable and, as of brunocodutra/metal@72115c2, pretty fast too ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants