Fix stencils over-transfer of neighbor data - #737
Open
jpsamaroo wants to merge 8 commits into
Open
Conversation
Contributor
Dagger benchmarks:
|
| master | dirty | master / dirty | |
|---|---|---|---|
| array/dagger/N=1024 (block 128)/add (X + X) | 23.9 ± 2.6 ms | 24.8 ± 2.5 ms | 0.963 ± 0.14 |
| array/dagger/N=1024 (block 128)/alloc (rand) | 18 ± 0.75 ms | 20.1 ± 0.36 ms | 0.894 ± 0.041 |
| array/dagger/N=1024 (block 128)/broadcast (X .+ 1) | 15.6 ± 0.86 ms | 18.2 ± 0.75 ms | 0.854 ± 0.059 |
| array/dagger/N=1024 (block 128)/map (sin.(X)) | 14.9 ± 1.2 ms | 17.6 ± 0.31 ms | 0.847 ± 0.068 |
| array/dagger/N=1024 (block 128)/norm | 16.6 ± 0.22 ms | 18.3 ± 0.59 ms | 0.903 ± 0.031 |
| array/dagger/N=1024 (block 128)/reduce (sum) | 28.9 ± 0.63 ms | 0.036 ± 0.0037 s | 0.802 ± 0.085 |
| array/dagger/N=1024 (block 128)/transpose (permutedims) | 16.8 ± 3.8 ms | 17.9 ± 0.73 ms | 0.939 ± 0.22 |
| array/dagger/N=1024 (block 512)/add (X + X) | 4.52 ± 0.83 ms | 4.96 ± 0.15 ms | 0.912 ± 0.17 |
| array/dagger/N=1024 (block 512)/alloc (rand) | 3.94 ± 0.17 ms | 4.58 ± 0.14 ms | 0.86 ± 0.047 |
| array/dagger/N=1024 (block 512)/broadcast (X .+ 1) | 3.01 ± 0.1 ms | 3.66 ± 0.29 ms | 0.821 ± 0.071 |
| array/dagger/N=1024 (block 512)/map (sin.(X)) | 7.39 ± 0.22 ms | 8.02 ± 0.76 ms | 0.921 ± 0.091 |
| array/dagger/N=1024 (block 512)/norm | 1.5 ± 0.39 ms | 1.78 ± 0.63 ms | 0.846 ± 0.37 |
| array/dagger/N=1024 (block 512)/reduce (sum) | 3.57 ± 1.9 ms | 3.73 ± 1.8 ms | 0.956 ± 0.68 |
| array/dagger/N=1024 (block 512)/transpose (permutedims) | 7.45 ± 0.36 ms | 9.02 ± 1.1 ms | 0.826 ± 0.11 |
| array/dagger/N=256 (block 128)/add (X + X) | 3.17 ± 0.55 ms | 2.89 ± 0.1 ms | 1.1 ± 0.19 |
| array/dagger/N=256 (block 128)/alloc (rand) | 2.39 ± 0.17 ms | 2.76 ± 0.3 ms | 0.865 ± 0.11 |
| array/dagger/N=256 (block 128)/broadcast (X .+ 1) | 1.58 ± 0.51 ms | 1.51 ± 3.8 ms | 1.05 ± 2.6 |
| array/dagger/N=256 (block 128)/map (sin.(X)) | 1.58 ± 0.2 ms | 1.75 ± 0.29 ms | 0.904 ± 0.19 |
| array/dagger/N=256 (block 128)/norm | 1.72 ± 0.17 ms | 1.52 ± 0.073 ms | 1.13 ± 0.12 |
| array/dagger/N=256 (block 128)/reduce (sum) | 3.98 ± 6.6 ms | 7.48 ± 2.9 ms | 0.533 ± 0.91 |
| array/dagger/N=256 (block 128)/transpose (permutedims) | 2.75 ± 2 ms | 2.69 ± 0.51 ms | 1.02 ± 0.77 |
| array/dagger/N=256 (block 256)/add (X + X) | 1.69 ± 0.2 ms | 1.64 ± 0.071 ms | 1.03 ± 0.13 |
| array/dagger/N=256 (block 256)/alloc (rand) | 1.45 ± 0.12 ms | 1.56 ± 0.21 ms | 0.928 ± 0.15 |
| array/dagger/N=256 (block 256)/broadcast (X .+ 1) | 0.723 ± 0.11 ms | 0.836 ± 0.2 ms | 0.865 ± 0.24 |
| array/dagger/N=256 (block 256)/map (sin.(X)) | 1.73 ± 0.21 ms | 1.57 ± 0.23 ms | 1.1 ± 0.21 |
| array/dagger/N=256 (block 256)/norm | 0.691 ± 0.055 ms | 0.886 ± 0.11 ms | 0.78 ± 0.11 |
| array/dagger/N=256 (block 256)/reduce (sum) | 1.28 ± 0.16 ms | 1.72 ± 0.4 ms | 0.748 ± 0.2 |
| array/dagger/N=256 (block 256)/transpose (permutedims) | 1.62 ± 0.22 ms | 1.42 ± 0.33 ms | 1.14 ± 0.31 |
| linalg/dagger/N=1024 (block 128)/cholesky | 0.132 ± 0.0068 s | 0.115 ± 0.0049 s | 1.14 ± 0.076 |
| linalg/dagger/N=1024 (block 128)/lu | 0.263 ± 0.0092 s | 0.27 ± 0.012 s | 0.977 ± 0.055 |
| linalg/dagger/N=1024 (block 128)/matmul (A*A) | 0.317 ± 0.027 s | 0.296 ± 0.015 s | 1.07 ± 0.11 |
| linalg/dagger/N=1024 (block 128)/matvec (A*x) | 0.034 ± 0.0016 s | 0.0337 ± 0.00092 s | 1.01 ± 0.056 |
| linalg/dagger/N=1024 (block 128)/qr | 0.282 ± 0.05 s | 0.221 ± 0.024 s | 1.27 ± 0.27 |
| linalg/dagger/N=1024 (block 128)/solve (A\b via lu) | 0.375 ± 0.0026 s | 0.337 ± 0.0092 s | 1.11 ± 0.031 |
| linalg/dagger/N=1024 (block 128)/svd | 28.9 s | 31.7 s | 0.912 |
| linalg/dagger/N=1024 (block 128)/syrk (A'*A) | 0.206 ± 0.011 s | 0.207 ± 0.029 s | 0.992 ± 0.15 |
| linalg/dagger/N=1024 (block 512)/cholesky | 25.3 ± 0.82 ms | 28.5 ± 2.7 ms | 0.887 ± 0.088 |
| linalg/dagger/N=1024 (block 512)/lu | 0.0521 ± 0.0058 s | 0.0518 ± 0.0031 s | 1.01 ± 0.13 |
| linalg/dagger/N=1024 (block 512)/matmul (A*A) | 0.0518 ± 0.0089 s | 0.0607 ± 0.012 s | 0.853 ± 0.22 |
| linalg/dagger/N=1024 (block 512)/matvec (A*x) | 4.21 ± 0.27 ms | 4.33 ± 1.5 ms | 0.971 ± 0.34 |
| linalg/dagger/N=1024 (block 512)/qr | 0.116 ± 0.0028 s | 0.129 ± 0.0024 s | 0.901 ± 0.028 |
| linalg/dagger/N=1024 (block 512)/solve (A\b via lu) | 0.0621 ± 0.0014 s | 0.0605 ± 0.0049 s | 1.03 ± 0.086 |
| linalg/dagger/N=1024 (block 512)/svd | 0.0352 h | 0.0392 h | 0.899 |
| linalg/dagger/N=1024 (block 512)/syrk (A'*A) | 0.0421 ± 0.00074 s | 0.0433 ± 0.004 s | 0.971 ± 0.09 |
| linalg/dagger/N=256 (block 128)/cholesky | 13.6 ± 11 ms | 7.53 ± 2.2 ms | 1.81 ± 1.5 |
| linalg/dagger/N=256 (block 128)/lu | 14.5 ± 5.6 ms | 16.7 ± 7.2 ms | 0.871 ± 0.51 |
| linalg/dagger/N=256 (block 128)/matmul (A*A) | 6.44 ± 1.4 ms | 7 ± 2.6 ms | 0.919 ± 0.39 |
| linalg/dagger/N=256 (block 128)/matvec (A*x) | 3.8 ± 0.15 ms | 6.2 ± 0.83 ms | 0.612 ± 0.086 |
| linalg/dagger/N=256 (block 128)/qr | 12.5 ± 2.1 ms | 14.6 ± 2.7 ms | 0.856 ± 0.21 |
| linalg/dagger/N=256 (block 128)/solve (A\b via lu) | 23.4 ± 2.3 ms | 26.1 ± 2.5 ms | 0.898 ± 0.13 |
| linalg/dagger/N=256 (block 128)/svd | 0.691 ± 0.096 s | 0.72 ± 0.067 s | 0.961 ± 0.16 |
| linalg/dagger/N=256 (block 128)/syrk (A'*A) | 8 ± 7.3 ms | 8.7 ± 1.7 ms | 0.919 ± 0.86 |
| linalg/dagger/N=256 (block 256)/cholesky | 3.99 ± 2.1 ms | 6.88 ± 2 ms | 0.58 ± 0.35 |
| linalg/dagger/N=256 (block 256)/lu | 6.42 ± 0.35 ms | 10.5 ± 1.6 ms | 0.613 ± 0.1 |
| linalg/dagger/N=256 (block 256)/matmul (A*A) | 4.86 ± 0.63 ms | 4.66 ± 0.65 ms | 1.04 ± 0.2 |
| linalg/dagger/N=256 (block 256)/matvec (A*x) | 2.01 ± 0.24 ms | 1.93 ± 0.56 ms | 1.04 ± 0.33 |
| linalg/dagger/N=256 (block 256)/qr | 7.49 ± 1.1 ms | 7.65 ± 2.2 ms | 0.979 ± 0.32 |
| linalg/dagger/N=256 (block 256)/solve (A\b via lu) | 13 ± 1.5 ms | 12.8 ± 2.2 ms | 1.02 ± 0.21 |
| linalg/dagger/N=256 (block 256)/svd | 0.546 ± 0.002 s | 0.639 ± 0.072 s | 0.854 ± 0.097 |
| linalg/dagger/N=256 (block 256)/syrk (A'*A) | 5.57 ± 1.3 ms | 6.93 ± 0.49 ms | 0.804 ± 0.2 |
| stencil/dagger/N=1024 (block 128)/alloc (neighbors Wrap) | 0.0488 ± 0.048 s | 0.0426 ± 0.0012 s | 1.15 ± 1.1 |
| stencil/dagger/N=1024 (block 128)/assign (const) | 16.6 ± 0.84 ms | 15.8 ± 0.36 ms | 1.05 ± 0.058 |
| stencil/dagger/N=1024 (block 128)/multi-expr | 0.0345 ± 0.0013 s | 0.0371 ± 0.0037 s | 0.931 ± 0.099 |
| stencil/dagger/N=1024 (block 128)/neighbors (Clamp) | 0.0332 ± 0.002 s | 30.6 ± 1.4 ms | 1.08 ± 0.081 |
| stencil/dagger/N=1024 (block 128)/neighbors (Pad) | 31.1 ± 2.3 ms | 0.0325 ± 0.0017 s | 0.958 ± 0.086 |
| stencil/dagger/N=1024 (block 128)/neighbors (Reflect) | 0.0332 ± 0.0062 s | 0.0324 ± 0.0021 s | 1.02 ± 0.2 |
| stencil/dagger/N=1024 (block 128)/neighbors (Wrap) | 0.0332 ± 0.00011 s | 0.0322 ± 0.00072 s | 1.03 ± 0.023 |
| stencil/dagger/N=1024 (block 128)/update (+) | 22.1 ± 1.8 ms | 17.1 ± 1.7 ms | 1.3 ± 0.17 |
| stencil/dagger/N=1024 (block 512)/alloc (neighbors Wrap) | 12.6 ± 1.1 ms | 10.5 ± 0.61 ms | 1.2 ± 0.13 |
| stencil/dagger/N=1024 (block 512)/assign (const) | 2.13 ± 0.28 ms | 1.97 ± 0.076 ms | 1.08 ± 0.15 |
| stencil/dagger/N=1024 (block 512)/multi-expr | 3.69 ± 0.15 ms | 4.52 ± 0.076 ms | 0.816 ± 0.036 |
| stencil/dagger/N=1024 (block 512)/neighbors (Clamp) | 9.4 ± 1 ms | 10.4 ± 0.96 ms | 0.904 ± 0.13 |
| stencil/dagger/N=1024 (block 512)/neighbors (Pad) | 9.98 ± 0.72 ms | 12 ± 1.3 ms | 0.829 ± 0.11 |
| stencil/dagger/N=1024 (block 512)/neighbors (Reflect) | 9.41 ± 0.39 ms | 9.67 ± 0.24 ms | 0.973 ± 0.047 |
| stencil/dagger/N=1024 (block 512)/neighbors (Wrap) | 8.37 ± 0.55 ms | 9.02 ± 0.36 ms | 0.928 ± 0.071 |
| stencil/dagger/N=1024 (block 512)/update (+) | 2.82 ± 0.32 ms | 3.2 ± 0.45 ms | 0.883 ± 0.16 |
| stencil/dagger/N=256 (block 128)/alloc (neighbors Wrap) | 4.49 ± 0.56 ms | 4.32 ± 1.5 ms | 1.04 ± 0.38 |
| stencil/dagger/N=256 (block 128)/assign (const) | 1.94 ± 0.28 ms | 2.19 ± 0.49 ms | 0.882 ± 0.23 |
| stencil/dagger/N=256 (block 128)/multi-expr | 4.42 ± 0.65 ms | 5.45 ± 1.2 ms | 0.812 ± 0.21 |
| stencil/dagger/N=256 (block 128)/neighbors (Clamp) | 3.37 ± 0.17 ms | 3.09 ± 0.24 ms | 1.09 ± 0.1 |
| stencil/dagger/N=256 (block 128)/neighbors (Pad) | 3.64 ± 0.89 ms | 3.39 ± 0.86 ms | 1.07 ± 0.38 |
| stencil/dagger/N=256 (block 128)/neighbors (Reflect) | 3.32 ± 0.28 ms | 3.28 ± 1.3 ms | 1.01 ± 0.42 |
| stencil/dagger/N=256 (block 128)/neighbors (Wrap) | 3.37 ± 0.19 ms | 5.32 ± 0.61 ms | 0.634 ± 0.08 |
| stencil/dagger/N=256 (block 128)/update (+) | 2.06 ± 0.43 ms | 1.97 ± 1.5 ms | 1.05 ± 0.83 |
| stencil/dagger/N=256 (block 256)/alloc (neighbors Wrap) | 3.21 ± 0.14 ms | 3.61 ± 0.09 ms | 0.889 ± 0.045 |
| stencil/dagger/N=256 (block 256)/assign (const) | 1.22 ± 0.16 ms | 1.07 ± 0.082 ms | 1.13 ± 0.17 |
| stencil/dagger/N=256 (block 256)/multi-expr | 1.84 ± 0.18 ms | 1.84 ± 0.11 ms | 0.999 ± 0.11 |
| stencil/dagger/N=256 (block 256)/neighbors (Clamp) | 2.86 ± 0.14 ms | 3.18 ± 0.11 ms | 0.899 ± 0.054 |
| stencil/dagger/N=256 (block 256)/neighbors (Pad) | 2.74 ± 0.22 ms | 2.53 ± 0.33 ms | 1.08 ± 0.17 |
| stencil/dagger/N=256 (block 256)/neighbors (Reflect) | 3.12 ± 1.7 ms | 2.9 ± 0.43 ms | 1.08 ± 0.62 |
| stencil/dagger/N=256 (block 256)/neighbors (Wrap) | 2.71 ± 0.089 ms | 3.13 ± 0.31 ms | 0.866 ± 0.092 |
| stencil/dagger/N=256 (block 256)/update (+) | 1.51 ± 0.12 ms | 1.44 ± 0.22 ms | 1.05 ± 0.18 |
| time_to_load | 1.31 ± 0.032 s | 1.28 ± 0.028 s | 1.02 ± 0.033 |
Plots
⚠️ Regressions (> 25.0%)
array/dagger/N=256 (block 128)/reduce (sum): +87.8%linalg/dagger/N=256 (block 256)/cholesky: +72.3%linalg/dagger/N=256 (block 128)/matvec (A*x): +63.3%linalg/dagger/N=256 (block 256)/lu: +63.1%stencil/dagger/N=256 (block 128)/neighbors (Wrap): +57.8%array/dagger/N=256 (block 256)/reduce (sum): +33.6%array/dagger/N=256 (block 256)/norm: +28.3%
Improvements (> 25.0% faster)
linalg/dagger/N=256 (block 128)/cholesky: -44.8%
Distributed benchmarks (4 processes)
Dagger benchmarks: dirty vs master
| master | dirty | master / dirty | |
|---|---|---|---|
| array/dagger/N=1024 (block 128)/add (X + X) | 30.8 ± 0.41 ms | 30.4 ± 0.12 ms | 1.01 ± 0.014 |
| array/dagger/N=1024 (block 128)/alloc (rand) | 16.6 ± 0.14 ms | 16.5 ± 0.13 ms | 1.01 ± 0.011 |
| array/dagger/N=1024 (block 128)/broadcast (X .+ 1) | 15.3 ± 0.13 ms | 15.3 ± 0.11 ms | 0.999 ± 0.011 |
| array/dagger/N=1024 (block 128)/map (sin.(X)) | 24.3 ± 0.36 ms | 24.7 ± 0.27 ms | 0.983 ± 0.018 |
| array/dagger/N=1024 (block 128)/norm | 11.5 ± 0.092 ms | 11.7 ± 0.06 ms | 0.985 ± 0.0094 |
| array/dagger/N=1024 (block 128)/reduce (sum) | 20.7 ± 0.11 ms | 20.8 ± 0.26 ms | 0.992 ± 0.013 |
| array/dagger/N=1024 (block 128)/transpose (permutedims) | 21.6 ± 6.4 ms | 21.4 ± 0.18 ms | 1.01 ± 0.3 |
| array/dagger/N=1024 (block 512)/add (X + X) | 6.28 ± 0.025 ms | 3.32 ± 0.06 ms | 1.89 ± 0.035 |
| array/dagger/N=1024 (block 512)/alloc (rand) | 6.09 ± 0.1 ms | 3.35 ± 0.063 ms | 1.82 ± 0.046 |
| array/dagger/N=1024 (block 512)/broadcast (X .+ 1) | 4.89 ± 0.21 ms | 1.69 ± 0.024 ms | 2.88 ± 0.13 |
| array/dagger/N=1024 (block 512)/map (sin.(X)) | 14.9 ± 0.25 ms | 11.8 ± 0.037 ms | 1.26 ± 0.022 |
| array/dagger/N=1024 (block 512)/norm | 1.27 ± 0.077 ms | 1.26 ± 0.047 ms | 1.01 ± 0.071 |
| array/dagger/N=1024 (block 512)/reduce (sum) | 2.25 ± 0.16 ms | 2.11 ± 0.082 ms | 1.06 ± 0.088 |
| array/dagger/N=1024 (block 512)/transpose (permutedims) | 14.2 ± 0.51 ms | 11.4 ± 0.046 ms | 1.24 ± 0.045 |
| array/dagger/N=256 (block 128)/add (X + X) | 2.29 ± 0.04 ms | 2.32 ± 0.82 ms | 0.988 ± 0.35 |
| array/dagger/N=256 (block 128)/alloc (rand) | 2.07 ± 0.031 ms | 2.11 ± 0.041 ms | 0.984 ± 0.024 |
| array/dagger/N=256 (block 128)/broadcast (X .+ 1) | 1.24 ± 0.079 ms | 1.21 ± 0.09 ms | 1.03 ± 0.1 |
| array/dagger/N=256 (block 128)/map (sin.(X)) | 1.81 ± 0.033 ms | 1.79 ± 0.019 ms | 1.01 ± 0.021 |
| array/dagger/N=256 (block 128)/norm | 1.02 ± 0.046 ms | 0.995 ± 0.0022 ms | 1.02 ± 0.047 |
| array/dagger/N=256 (block 128)/reduce (sum) | 1.95 ± 0.41 ms | 2.05 ± 0.39 ms | 0.952 ± 0.27 |
| array/dagger/N=256 (block 128)/transpose (permutedims) | 1.9 ± 0.18 ms | 1.94 ± 0.033 ms | 0.979 ± 0.097 |
| array/dagger/N=256 (block 256)/add (X + X) | 1.4 ± 0.037 ms | 1.4 ± 0.02 ms | 1 ± 0.03 |
| array/dagger/N=256 (block 256)/alloc (rand) | 1.43 ± 0.019 ms | 1.44 ± 0.056 ms | 0.996 ± 0.041 |
| array/dagger/N=256 (block 256)/broadcast (X .+ 1) | 0.724 ± 0.12 ms | 0.733 ± 0.012 ms | 0.988 ± 0.16 |
| array/dagger/N=256 (block 256)/map (sin.(X)) | 1.36 ± 0.15 ms | 1.38 ± 0.04 ms | 0.988 ± 0.11 |
| array/dagger/N=256 (block 256)/norm | 0.464 ± 0.052 ms | 0.479 ± 0.018 ms | 0.969 ± 0.11 |
| array/dagger/N=256 (block 256)/reduce (sum) | 0.799 ± 0.062 ms | 0.879 ± 0.0059 ms | 0.909 ± 0.071 |
| array/dagger/N=256 (block 256)/transpose (permutedims) | 1.28 ± 0.072 ms | 1.31 ± 0.048 ms | 0.982 ± 0.066 |
| linalg/dagger/N=1024 (block 128)/cholesky | 0.065 ± 0.0058 s | 0.074 ± 0.0032 s | 0.879 ± 0.087 |
| linalg/dagger/N=1024 (block 128)/lu | 0.17 ± 0.00096 s | 0.168 ± 0.00097 s | 1.01 ± 0.0082 |
| linalg/dagger/N=1024 (block 128)/matmul (A*A) | 0.186 ± 0.014 s | 0.171 ± 0.00011 s | 1.09 ± 0.083 |
| linalg/dagger/N=1024 (block 128)/matvec (A*x) | 26.3 ± 0.6 ms | 26.9 ± 0.37 ms | 0.978 ± 0.026 |
| linalg/dagger/N=1024 (block 128)/qr | 0.246 ± 0.0014 s | 0.245 ± 9.7e-05 s | 1.01 ± 0.0058 |
| linalg/dagger/N=1024 (block 128)/solve (A\b via lu) | 0.211 ± 0.002 s | 0.209 ± 0.00014 s | 1.01 ± 0.0098 |
| linalg/dagger/N=1024 (block 128)/svd | 52.3 s | 51.1 s | 1.02 |
| linalg/dagger/N=1024 (block 128)/syrk (A'*A) | 0.112 ± 0.0019 s | 0.112 ± 0.0016 s | 1 ± 0.022 |
| linalg/dagger/N=1024 (block 512)/cholesky | 22.1 ± 0.49 ms | 22.1 ± 0.82 ms | 1 ± 0.043 |
| linalg/dagger/N=1024 (block 512)/lu | 0.0448 ± 0.0015 s | 0.0454 ± 0.00023 s | 0.988 ± 0.034 |
| linalg/dagger/N=1024 (block 512)/matmul (A*A) | 0.0364 ± 3.9e-05 s | 0.0403 ± 0.0028 s | 0.903 ± 0.062 |
| linalg/dagger/N=1024 (block 512)/matvec (A*x) | 3.21 ± 0.11 ms | 3.44 ± 0.12 ms | 0.935 ± 0.045 |
| linalg/dagger/N=1024 (block 512)/qr | 0.104 ± 0.00058 s | 0.104 ± 0.00076 s | 1.01 ± 0.0093 |
| linalg/dagger/N=1024 (block 512)/solve (A\b via lu) | 0.0489 ± 0.00056 s | 0.0479 ± 0.00048 s | 1.02 ± 0.016 |
| linalg/dagger/N=1024 (block 512)/svd | 0.0394 h | 0.0393 h | 1 |
| linalg/dagger/N=1024 (block 512)/syrk (A'*A) | 30.7 ± 0.17 ms | 30.7 ± 0.21 ms | 1 ± 0.0086 |
| linalg/dagger/N=256 (block 128)/cholesky | 5.65 ± 0.53 ms | 4.64 ± 0.041 ms | 1.22 ± 0.11 |
| linalg/dagger/N=256 (block 128)/lu | 8.43 ± 0.18 ms | 8.29 ± 0.053 ms | 1.02 ± 0.022 |
| linalg/dagger/N=256 (block 128)/matmul (A*A) | 5.35 ± 0.35 ms | 6.15 ± 0.34 ms | 0.87 ± 0.074 |
| linalg/dagger/N=256 (block 128)/matvec (A*x) | 2.83 ± 0.031 ms | 2.92 ± 0.11 ms | 0.971 ± 0.037 |
| linalg/dagger/N=256 (block 128)/qr | 8 ± 0.086 ms | 8.54 ± 0.37 ms | 0.937 ± 0.041 |
| linalg/dagger/N=256 (block 128)/solve (A\b via lu) | 14.1 ± 0.17 ms | 15.4 ± 0.75 ms | 0.92 ± 0.046 |
| linalg/dagger/N=256 (block 128)/svd | 0.536 ± 0.056 s | 0.874 ± 0.025 s | 0.613 ± 0.067 |
| linalg/dagger/N=256 (block 128)/syrk (A'*A) | 5.77 ± 0.16 ms | 5.97 ± 0.058 ms | 0.966 ± 0.028 |
| linalg/dagger/N=256 (block 256)/cholesky | 2.38 ± 0.075 ms | 2.93 ± 0.21 ms | 0.813 ± 0.063 |
| linalg/dagger/N=256 (block 256)/lu | 4.21 ± 0.066 ms | 4.02 ± 0.043 ms | 1.05 ± 0.02 |
| linalg/dagger/N=256 (block 256)/matmul (A*A) | 2.1 ± 0.072 ms | 2.26 ± 0.21 ms | 0.93 ± 0.091 |
| linalg/dagger/N=256 (block 256)/matvec (A*x) | 1.48 ± 0.013 ms | 1.49 ± 0.012 ms | 0.997 ± 0.012 |
| linalg/dagger/N=256 (block 256)/qr | 4.63 ± 0.03 ms | 4.97 ± 0.25 ms | 0.931 ± 0.048 |
| linalg/dagger/N=256 (block 256)/solve (A\b via lu) | 6.65 ± 0.1 ms | 7.24 ± 0.00082 ms | 0.918 ± 0.014 |
| linalg/dagger/N=256 (block 256)/svd | 0.622 ± 0.0034 s | 0.402 ± 0.062 s | 1.55 ± 0.24 |
| linalg/dagger/N=256 (block 256)/syrk (A'*A) | 2.94 ± 0.17 ms | 3.25 ± 0.073 ms | 0.905 ± 0.056 |
| stencil/dagger/N=1024 (block 128)/alloc (neighbors Wrap) | 0.041 ± 0.0003 s | 0.0404 ± 0.00011 s | 1.01 ± 0.0078 |
| stencil/dagger/N=1024 (block 128)/assign (const) | 11.1 ± 0.025 ms | 11.1 ± 0.027 ms | 1 ± 0.0034 |
| stencil/dagger/N=1024 (block 128)/multi-expr | 24.4 ± 0.27 ms | 24.3 ± 0.12 ms | 1 ± 0.012 |
| stencil/dagger/N=1024 (block 128)/neighbors (Clamp) | 0.0324 ± 5.3e-05 s | 0.0329 ± 0.0001 s | 0.985 ± 0.0034 |
| stencil/dagger/N=1024 (block 128)/neighbors (Pad) | 0.0327 ± 2.1e-05 s | 0.0329 ± 0.00012 s | 0.994 ± 0.0036 |
| stencil/dagger/N=1024 (block 128)/neighbors (Reflect) | 0.0329 ± 1.9e-05 s | 0.0332 ± 3.6e-05 s | 0.992 ± 0.0012 |
| stencil/dagger/N=1024 (block 128)/neighbors (Wrap) | 0.0332 ± 0.00011 s | 0.0334 ± 4.3e-05 s | 0.994 ± 0.0034 |
| stencil/dagger/N=1024 (block 128)/update (+) | 14 ± 0.051 ms | 14 ± 0.029 ms | 0.998 ± 0.0042 |
| stencil/dagger/N=1024 (block 512)/alloc (neighbors Wrap) | 12.1 ± 0.033 ms | 12.5 ± 0.03 ms | 0.971 ± 0.0036 |
| stencil/dagger/N=1024 (block 512)/assign (const) | 1.46 ± 0.044 ms | 1.59 ± 0.013 ms | 0.922 ± 0.029 |
| stencil/dagger/N=1024 (block 512)/multi-expr | 2.88 ± 0.0014 ms | 3.18 ± 0.0099 ms | 0.905 ± 0.0028 |
| stencil/dagger/N=1024 (block 512)/neighbors (Clamp) | 11.2 ± 0.082 ms | 11.6 ± 0.023 ms | 0.966 ± 0.0074 |
| stencil/dagger/N=1024 (block 512)/neighbors (Pad) | 11.1 ± 0.087 ms | 11.6 ± 0.017 ms | 0.95 ± 0.0076 |
| stencil/dagger/N=1024 (block 512)/neighbors (Reflect) | 11.4 ± 0.00078 ms | 11.6 ± 0.029 ms | 0.987 ± 0.0025 |
| stencil/dagger/N=1024 (block 512)/neighbors (Wrap) | 11.6 ± 0.09 ms | 11.6 ± 0.033 ms | 1 ± 0.0082 |
| stencil/dagger/N=1024 (block 512)/update (+) | 2.27 ± 0.067 ms | 2.33 ± 0.0041 ms | 0.973 ± 0.029 |
| stencil/dagger/N=256 (block 128)/alloc (neighbors Wrap) | 3.29 ± 0.041 ms | 3.3 ± 0.049 ms | 0.997 ± 0.019 |
| stencil/dagger/N=256 (block 128)/assign (const) | 1.27 ± 0.051 ms | 1.36 ± 0.043 ms | 0.931 ± 0.048 |
| stencil/dagger/N=256 (block 128)/multi-expr | 2.43 ± 0.0051 ms | 2.5 ± 0.036 ms | 0.973 ± 0.014 |
| stencil/dagger/N=256 (block 128)/neighbors (Clamp) | 2.83 ± 0.22 ms | 2.85 ± 0.047 ms | 0.994 ± 0.079 |
| stencil/dagger/N=256 (block 128)/neighbors (Pad) | 2.63 ± 0.022 ms | 2.76 ± 0.034 ms | 0.952 ± 0.014 |
| stencil/dagger/N=256 (block 128)/neighbors (Reflect) | 2.67 ± 0.081 ms | 2.77 ± 0.041 ms | 0.964 ± 0.033 |
| stencil/dagger/N=256 (block 128)/neighbors (Wrap) | 2.68 ± 0.09 ms | 2.8 ± 0.022 ms | 0.957 ± 0.033 |
| stencil/dagger/N=256 (block 128)/update (+) | 1.46 ± 0.014 ms | 1.51 ± 0.03 ms | 0.967 ± 0.021 |
| stencil/dagger/N=256 (block 256)/alloc (neighbors Wrap) | 1.83 ± 0.011 ms | 1.89 ± 0.037 ms | 0.972 ± 0.02 |
| stencil/dagger/N=256 (block 256)/assign (const) | 0.816 ± 0.028 ms | 0.778 ± 0.0099 ms | 1.05 ± 0.038 |
| stencil/dagger/N=256 (block 256)/multi-expr | 1.3 ± 0.088 ms | 1.43 ± 0.052 ms | 0.909 ± 0.07 |
| stencil/dagger/N=256 (block 256)/neighbors (Clamp) | 1.62 ± 0.015 ms | 1.72 ± 0.0071 ms | 0.941 ± 0.0094 |
| stencil/dagger/N=256 (block 256)/neighbors (Pad) | 1.61 ± 0.025 ms | 1.68 ± 0.00041 ms | 0.957 ± 0.015 |
| stencil/dagger/N=256 (block 256)/neighbors (Reflect) | 1.75 ± 0.04 ms | 1.68 ± 0.02 ms | 1.04 ± 0.027 |
| stencil/dagger/N=256 (block 256)/neighbors (Wrap) | 1.67 ± 0.02 ms | 1.67 ± 0.036 ms | 1 ± 0.025 |
| stencil/dagger/N=256 (block 256)/update (+) | 0.91 ± 0.02 ms | 0.928 ± 0.0063 ms | 0.981 ± 0.023 |
| time_to_load | 1.11 ± 0.013 s | 1.12 ± 0.0056 s | 0.995 ± 0.013 |
Plots
⚠️ Regressions (> 35.0%)
linalg/dagger/N=256 (block 128)/svd: +63.1%
Improvements (> 35.0% faster)
array/dagger/N=1024 (block 512)/broadcast (X .+ 1): -65.3%array/dagger/N=1024 (block 512)/add (X + X): -47.0%array/dagger/N=1024 (block 512)/alloc (rand): -44.9%linalg/dagger/N=256 (block 256)/svd: -35.4%
MPI benchmarks (4 ranks)
Results unavailable (job did not produce a report).
Full results and plots (download the benchmark-results-* artifacts).
jpsamaroo
force-pushed
the
jps/mpi-bad-scale-stencil
branch
from
August 17, 2026 22:36
3e7eedb to
3c0b231
Compare
…ronment MPI.mpiexec(identity) only extracted the executable/Cmd; MPI.jl's mpiexec() sets up the environment the binary needs (library paths for the bundled MPICH_jll, etc.) only for the dynamic extent of its callback, so running the extracted command afterwards spawned a process missing that environment, which died immediately before worker_mpi.jl could produce any results. Move the run(...; wait=false) call inside the `do` block, mirroring test/run_mpi.jl.
Sweep BENCHMARK_BLOCKSIZE instead of pinning one tile. The three benchmark jobs ran BENCHMARK_SCALE='[256, 1024]' with the tile left at square_block's default of 512, which makes N=256 a *single* chunk (it returns N when N <= tile) and N=1024 only 2x2 -- so anything touching data distribution, halo exchange or cross-space transfer was a no-op at one size and barely exercised at the other. Simply lowering the tile would trade one blind spot for another: tile size sets the ratio of per-tile task overhead to bytes moved per transfer, and a data-movement change can be a large win at one tile and a regression at the other. Measured under MPI on 4 ranks, commit c60e294 is ~25% slower at tile 128 and ~1.5-2x faster at tile 512 -- opposite conclusions from the same code. So BENCHMARK_BLOCKSIZE now takes a list, like BENCHMARK_SCALE. common.jl gains `blocksizes` and `blocks_for(N)`, and the three dense suites gain an inner loop over it. `blocks_for` de-duplicates tiles that collapse to the same block at a given N (at N=256 both 512 and 256 give 256), which matters because the groups are keyed "N=$N (block $b)" and would otherwise collide. CI uses '[128, 512]'; an unset variable still means a single tile of 512, as before.
`gather_free_syncdeps!` decided whether it could inspect a free candidate's backing buffer via `aliasing_available`, which under MPI was true only on the rank owning the ref. But `aliasing` is *collective* there -- the owner computes and broadcasts -- so the owning rank alone would enter a broadcast no other rank was in. That consumed a tag on one rank, desynchronizing every subsequent `to_tag`, and then deadlocked in the copy cycles at region end. Symptom on this branch: 26 errors per rank in `test/mpi.jl` (Cholesky, LU, and every `@stencil` case), all `ArgumentError: Non-uniform value` raised from `take_ref_id!`. Bisected to 87273af -- not because that commit is wrong, but because ranking by written args moves each task onto the rank owning the chunk it writes, which is what first makes a buffer underlie only wrapper arguments and so reach this branch at all. Every rank now takes the rank-uniform `key_ainfo` fallback whenever execution is uniform, so the decision depends solely on `uniform_execution()`. That leaves `aliasing_available` with no remaining call site -- `uniform_execution(::MPIAcceleration)` is unconditionally `true`, so the MPIRef method could never be reached past the short-circuit -- so it is removed along with its generic fallback. `test/mpi.jl` goes from 26 errors per rank to 0 (395/397/385/373 passing, no failures); Distributed datadeps is unchanged at 1272 passing. Also adds a "Partial slot currency" testset covering the case that motivated this: writing through a `ChunkView` on a non-owner rank and then reading the whole parent there, which must see the view's write and pull the rest from the owner. Its expectation is snapshotted *before* the region -- `A` is a non-Chunk argument, so rank 0 owns it and Datadeps writes back into it in place; deriving the baseline afterwards folds the update in and then adds it again (and only rank 0's copy is written back, so it would also disagree across ranks).
`gather_free_syncdeps!`'s uniform-execution fallback syncs on the cache key
ainfo, but guarded that on the key being tracked:
haskey(state.ainfos_overlaps, wrapped) &&
get_write_deps!(state, space, wrapped, write_num, syncdeps)
The key ainfo describes the original object in its *source* space, so it is
frequently not one of the tracked destination-space ainfos -- rank-stamped spans
mean it cannot overlap them, and the interval tree cannot be queried with it
either. When that happens the guard short-circuits and the `unsafe_free!` task is
spawned with an **empty syncdep set**, racing every task still reading the
buffer. Instrumenting a 64x64 / Blocks(16,16) Cholesky under 4 ranks shows a
handful of such frees per rank (`nsyncdeps=0`) among ~100 with 2-3.
This is normally invisible: the freed Libc block is recycled by the next
`alloc_libc_array`, and `move_rewrap` immediately overwrites it with a full copy
of the real data, so a use-after-free read gets plausible -- finite, usually
identical -- values.
The untracked case now syncs against every tracked ainfo in the space instead: a
strict over-approximation of what can overlap the buffer, and cheap, since frees
happen once per buffer at region end and only untracked keys take this branch.
`get_write_deps!` already covers both writers and readers, so the tracked case
was fine as-is.
`test/mpi.jl` is unchanged at 395/397/385/373 passing, no failures or errors.
A Datadeps slot's contents are never assumed to be current. `generate_slot!` says so outright -- it deliberately does not sync with the owner -- and `compute_remainder_for_arg!` decides what to copy purely from `arg_history` / `arg_owner`, never from the buffer. A slot in a space that does not yet appear in the argument's history is therefore always filled by a copy-to (`FullCopy`, or a span-exact `MultiRemainderAliasing` once part of it is current) before any task can read it. So for a dense, isbits payload crossing a space boundary, `move_rewrap` was sending bytes that were guaranteed to be overwritten. It now allocates the destination buffer and sends nothing: only the element type and dimensions travel (broadcast like a header under MPI, closure arguments under Distributed). The allocation is Libc-backed straight from `alloc_libc_array` rather than allocated and then copied into Libc memory by `libc_backed`, since there is nothing to copy. Under MPI that also fixes a latent no-op -- `libc_backed` was being applied to a `Chunk`, which hits the identity method. `from_space != to_space` is the load-bearing guard. When the two coincide the leaf transfer is the identity, so the "slot" *is* the original data and `compute_remainder_for_arg!` returns `NoAliasing()`; handing back a fresh buffer there would silently discard the argument. Allocation also stays routed through `aliased_object!`, so an already-present parent is still reused rather than shadowed by a detached buffer -- which is what keeps an array and its view sharing one destination allocation. N.B. This depends on the preceding free-syncdeps fix. Transferring the slot was masking a use-after-free: a recycled Libc block was immediately overwritten with real data, so a racing read returned plausible values. Without the transfer the same read hits uninitialized memory, which is how that bug first became visible (NaN out of a distributed Cholesky). Measured on 4 MPI ranks, a 1024x1024 `@stencil` sweep with `@neighbors`: 689ms/sweep at 128x128 tiles (872ms before) and 316ms at 512x512 tiles (509ms before). `test/mpi.jl` 398/403/388/376 passing; Distributed datadeps 1272 passing. Test contract updated accordingly: cross-space slots are no longer asserted to hold a copy of the source, only to have the right shape, type, and parent sharing; same-space slots must still be the real data. Two new testsets cover the allocation itself and the partial-currency invariant it rests on -- a task reading spans never written in its own space.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a regression introduced by prior stencil optimizations, which improved multi-threaded execution but significantly regressed multi-process and multi-rank.
Written by Claude Opus