Skip to content

Commit

Permalink
yet more atomics & cache-line fixes on work-stealing queue (#53424)
Browse files Browse the repository at this point in the history
This regression at a large number of GC threads still shows up on a
large aarch64 machine (80-core ARM Neoverse N1).

```
bench = "many_refs.jl"
(gcthreads, threads) = (1, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       3807 │    2826 │      2633 │        193 │          960 │                13 │      892 │         74 │
│  median │       3810 │    2826 │      2633 │        193 │          961 │                15 │      892 │         74 │
│ maximum │       3810 │    2831 │      2638 │        193 │          962 │                27 │      892 │         74 │
│   stdev │          2 │       3 │         3 │          0 │            1 │                 7 │        0 │          0 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (2, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2455 │    1476 │      1350 │        126 │          488 │                20 │      892 │         60 │
│  median │       2459 │    1478 │      1352 │        126 │          489 │                23 │      892 │         60 │
│ maximum │       2465 │    1479 │      1352 │        126 │          489 │                23 │      893 │         60 │
│   stdev │          5 │       1 │         1 │          0 │            1 │                 2 │        0 │          0 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (4, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2173 │    1194 │      1115 │         77 │          463 │                18 │      892 │         54 │
│  median │       2187 │    1194 │      1116 │         78 │          463 │                19 │      893 │         55 │
│ maximum │       2217 │    1208 │      1130 │         78 │          463 │                19 │      893 │         55 │
│   stdev │         22 │       8 │         8 │          1 │            0 │                 1 │        0 │          0 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (8, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2191 │    1212 │      1149 │         63 │          539 │                19 │      901 │         55 │
│  median │       2199 │    1219 │      1156 │         63 │          540 │                20 │      901 │         55 │
│ maximum │       2201 │    1222 │      1157 │         65 │          540 │                20 │      901 │         56 │
│   stdev │          5 │       5 │         4 │          1 │            1 │                 1 │        0 │          0 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (16, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       3897 │    2916 │      2854 │         60 │         1423 │                20 │      902 │         75 │
│  median │       4012 │    3032 │      2972 │         62 │         1491 │                21 │      904 │         75 │
│ maximum │       4026 │    3106 │      3044 │         62 │         1511 │                22 │      904 │         77 │
│   stdev │         70 │      96 │        96 │          1 │           46 │                 1 │        1 │          1 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
```

This patch seems to improve performance at 16 GC threads though we still
have some negative scaling for this benchmark beyond 8 GC threads
(others seem fine). I didn't test whether this is indeed the optimal
struct layout for the queue in this benchmark.

```
bench = "many_refs.jl"
(gcthreads, threads) = (1, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       3807 │    2822 │      2630 │        193 │          959 │                15 │      892 │         74 │
│  median │       3824 │    2823 │      2630 │        193 │          959 │                15 │      892 │         74 │
│ maximum │       4307 │    3194 │      2974 │        220 │         1086 │                19 │      892 │         74 │
│   stdev │        284 │     215 │       199 │         16 │           74 │                 2 │        0 │          0 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (2, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2459 │    1476 │      1349 │        126 │          488 │                19 │      892 │         60 │
│  median │       2460 │    1479 │      1352 │        127 │          488 │                21 │      893 │         60 │
│ maximum │       2770 │    1661 │      1526 │        135 │          570 │                22 │      893 │         60 │
│   stdev │        179 │     106 │       101 │          5 │           47 │                 1 │        0 │          0 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (4, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2215 │    1233 │      1155 │         77 │          485 │                20 │      892 │         53 │
│  median │       2320 │    1248 │      1171 │         78 │          492 │                21 │      893 │         54 │
│ maximum │       2372 │    1259 │      1176 │         83 │          493 │                22 │      893 │         56 │
│   stdev │         80 │      13 │        11 │          3 │            5 │                 1 │        1 │          1 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (8, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2204 │    1220 │      1156 │         64 │          544 │                23 │      901 │         53 │
│  median │       2362 │    1249 │      1181 │         64 │          553 │                23 │      901 │         53 │
│ maximum │       2374 │    1261 │      1196 │         68 │          558 │                25 │      901 │         55 │
│   stdev │         95 │      21 │        20 │          2 │            7 │                 1 │        0 │          1 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
(gcthreads, threads) = (16, 1)
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
[ Info: Setting GC memory pressure callback
┌─────────┬────────────┬─────────┬───────────┬────────────┬──────────────┬───────────────────┬──────────┬────────────┐
│         │ total time │ gc time │ mark time │ sweep time │ max GC pause │ time to safepoint │ max heap │ percent gc │
│         │         ms │      ms │        ms │         ms │           ms │                us │       MB │          % │
├─────────┼────────────┼─────────┼───────────┼────────────┼──────────────┼───────────────────┼──────────┼────────────┤
│ minimum │       2502 │    1519 │      1458 │         62 │          721 │                22 │      902 │         58 │
│  median │       2511 │    1524 │      1461 │         63 │          728 │                23 │      903 │         61 │
│ maximum │       2664 │    1554 │      1486 │         68 │          741 │                25 │      905 │         61 │
│   stdev │         91 │      19 │        16 │          3 │           10 │                 1 │        2 │          1 │
└─────────┴────────────┴─────────┴───────────┴────────────┴──────────────┴───────────────────┴──────────┴────────────┘
```
  • Loading branch information
d-netto committed Mar 4, 2024
1 parent 4d5a20d commit 973b4ff
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions src/work-stealing-queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#ifndef WORK_STEALING_QUEUE_H
#define WORK_STEALING_QUEUE_H

#include <stdalign.h>

#include "julia_atomics.h"
#include "assert.h"

Expand Down Expand Up @@ -41,10 +43,10 @@ static inline void free_ws_array(ws_array_t *a)
}

typedef struct {
_Atomic(int64_t) top;
char _padding[JL_CACHE_BYTE_ALIGNMENT - sizeof(_Atomic(int64_t))];
_Atomic(int64_t) bottom; // put on a separate cache line. conservatively estimate cache line size as 128 bytes
_Atomic(ws_array_t *) array;
// align to JL_CACHE_BYTE_ALIGNMENT
alignas(JL_CACHE_BYTE_ALIGNMENT) _Atomic(int64_t) top;
alignas(JL_CACHE_BYTE_ALIGNMENT) _Atomic(int64_t) bottom;
alignas(JL_CACHE_BYTE_ALIGNMENT) _Atomic(ws_array_t *) array;
} ws_queue_t;

static inline ws_array_t *ws_queue_push(ws_queue_t *q, void *elt, int32_t eltsz) JL_NOTSAFEPOINT
Expand Down

0 comments on commit 973b4ff

Please sign in to comment.