fastmixture2 2.0.3__tar.gz → 2.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastmixture2-2.0.3/fastmixture2.egg-info → fastmixture2-2.0.4}/PKG-INFO +50 -26
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/README.md +47 -23
- fastmixture2-2.0.4/fastmixture2/__init__.py +1 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/defaults.py +3 -3
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/em.pyx +10 -19
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/fastmixture2.py +13 -10
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/gpu.py +341 -240
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/main.py +1 -1
- fastmixture2-2.0.4/fastmixture2/packed.pxd +261 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/shared.pyx +12 -21
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/sqp.pyx +43 -5
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/svd.pyx +17 -1
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/utils.py +143 -40
- {fastmixture2-2.0.3 → fastmixture2-2.0.4/fastmixture2.egg-info}/PKG-INFO +50 -26
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2.egg-info/SOURCES.txt +4 -4
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/pyproject.toml +3 -2
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/check_portable.py +1 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/helpers.py +28 -2
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_cli.py +23 -16
- fastmixture2-2.0.4/tests/test_cpu_subset.py +331 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_cross_validation.py +8 -15
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_frequency_cache.py +15 -19
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_genotypes.py +44 -1
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_called.py +7 -3
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_gl_precision.py +28 -5
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_large.py +2 -1
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_modes.py +8 -6
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_precision.py +321 -8
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_safety.py +126 -8
- fastmixture2-2.0.4/tests/test_gpu_streamed.py +401 -0
- fastmixture2-2.0.4/tests/test_gpu_subset.py +501 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_svd_cache.py +7 -9
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_initialization.py +50 -13
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_numerical_equivalence.py +22 -1
- fastmixture2-2.0.4/tests/test_sqp_solver.py +435 -0
- fastmixture2-2.0.4/tests/test_subset_modes.py +360 -0
- fastmixture2-2.0.3/fastmixture2/__init__.py +0 -1
- fastmixture2-2.0.3/fastmixture2/packed.pxd +0 -144
- fastmixture2-2.0.3/tests/test_gpu_als.py +0 -214
- fastmixture2-2.0.3/tests/test_gpu_boot_precision.py +0 -159
- fastmixture2-2.0.3/tests/test_gpu_em_reduction.py +0 -114
- fastmixture2-2.0.3/tests/test_gpu_native_precision.py +0 -76
- fastmixture2-2.0.3/tests/test_sqp_solver.py +0 -177
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/LICENSE +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/MANIFEST.in +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/functions.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/kernels.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2/threads.pxd +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2.egg-info/dependency_links.txt +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2.egg-info/entry_points.txt +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2.egg-info/requires.txt +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/fastmixture2.egg-info/top_level.txt +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/setup.cfg +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/setup.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/run_tests.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_adversarial_io.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_bootstrap.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_convergence.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_cpu_scaling.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_distribution.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_stat_reuse.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_gpu_supervision.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_likelihoods.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_optimizers.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_q_constraints.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_sqp_scoring.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/test_threads.py +0 -0
- {fastmixture2-2.0.3 → fastmixture2-2.0.4}/tests/validate_distribution.py +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmixture2
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary:
|
|
5
|
-
Author-email:
|
|
3
|
+
Version: 2.0.4
|
|
4
|
+
Summary: Biobank-scale ancestry estimation in unrelated individuals
|
|
5
|
+
Author-email: "J. Meisner" <meisnerucph@gmail.com>, "L. Thunegard" <lisathunegard@icloud.com>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
7
7
|
Project-URL: Homepage, https://github.com/MeisnerLab/fastmixture2
|
|
8
8
|
Project-URL: Documentation, https://github.com/MeisnerLab/fastmixture2#readme
|
|
@@ -32,13 +32,14 @@ Dynamic: license-file
|
|
|
32
32
|
# fastmixture2
|
|
33
33
|
|
|
34
34
|
[](https://github.com/MeisnerLab/fastmixture2/actions/workflows/ci.yml)
|
|
35
|
-
[](https://pypi.org/project/fastmixture2/)
|
|
36
|
+
[](https://github.com/MeisnerLab/fastmixture2/blob/main/LICENSE)
|
|
36
37
|
|
|
37
38
|
`fastmixture2` estimates ancestry proportions (`Q`) and ancestral allele
|
|
38
39
|
frequencies (`P`) by maximum likelihood. It reads SNP-major PLINK genotypes
|
|
39
40
|
or ANGSD Beagle genotype likelihoods. Unsupervised initialization uses SVD/ALS
|
|
40
|
-
for K > 1
|
|
41
|
-
on NVIDIA CUDA.
|
|
41
|
+
for K > 1, with subset likelihood refinement for large panels.
|
|
42
|
+
All modes use safeguarded SQP/ZAL updates on CPU or, with `--gpu`, on NVIDIA CUDA.
|
|
42
43
|
|
|
43
44
|
## Installation
|
|
44
45
|
|
|
@@ -58,7 +59,8 @@ Source builds need a C compiler with OpenMP. On macOS, install OpenMP with
|
|
|
58
59
|
`brew install libomp`. On HPC, build on the compute-node type used for your
|
|
59
60
|
analyses.
|
|
60
61
|
|
|
61
|
-
With Conda, the [CPU](environment-cpu.yml)
|
|
62
|
+
With Conda, the [CPU](https://github.com/MeisnerLab/fastmixture2/blob/main/environment-cpu.yml)
|
|
63
|
+
and [GPU](https://github.com/MeisnerLab/fastmixture2/blob/main/environment-gpu.yml)
|
|
62
64
|
environments retain native CPU tuning. Run from the cloned repository:
|
|
63
65
|
|
|
64
66
|
```bash
|
|
@@ -69,7 +71,7 @@ conda activate fastmixture2-cpu
|
|
|
69
71
|
For GPU use, select `environment-gpu.yml` and activate `fastmixture2-gpu`.
|
|
70
72
|
|
|
71
73
|
PyPI wheels cover Linux (glibc) and macOS 14 or newer, on x86-64 and ARM64.
|
|
72
|
-
They
|
|
74
|
+
They use AVX2 on supported x86-64 CPUs and NEON on ARM64, including Apple Silicon:
|
|
73
75
|
|
|
74
76
|
```bash
|
|
75
77
|
python -m pip install fastmixture2
|
|
@@ -132,20 +134,39 @@ fastmixture2 --bfile cohort --K 5 --threads 8 --gpu --out cohort.gpu
|
|
|
132
134
|
CPU and CUDA support `1 <= K <= 128` for both input formats in all modes.
|
|
133
135
|
CUDA keeps input data on the GPU when they fit and streams in blocks otherwise.
|
|
134
136
|
Small CPU/GPU differences can arise from floating-point arithmetic.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
then
|
|
137
|
+
|
|
138
|
+
At K > 1, unsupervised initialization uses 10 SVD power iterations on all SNPs
|
|
139
|
+
up to 50,000, or a genome-wide 50,000-SNP subset otherwise. Larger panels refine
|
|
140
|
+
subset Q/P with SQP/ZAL, then fit full-marker P by least squares at fixed Q and
|
|
141
|
+
retain the refined subset rows. This applies to both input formats, including
|
|
142
|
+
missing genotypes.
|
|
143
|
+
Panels up to 50,000 SNPs proceed directly from SVD/ALS to full-data refinement,
|
|
144
|
+
without a duplicate subset fit or projection. For PLINK, subset refinement is
|
|
145
|
+
skipped if any sample has no observed subset genotypes. Exact CV folds and
|
|
146
|
+
`--iter 0` retain SVD/ALS without subset likelihood refinement.
|
|
147
|
+
|
|
148
|
+
Subsets exceeding 512 MiB on CPU or 256 MiB on CUDA are built in bounded blocks
|
|
149
|
+
into a temporary memory-mapped file. CUDA streams the subset when it does not
|
|
150
|
+
fit in VRAM. Temporary files use `TMPDIR`, which can point to disk-backed scratch
|
|
151
|
+
storage.
|
|
152
|
+
|
|
153
|
+
CUDA SVD starts at 256 samples. Both devices use CPU ALS with float64
|
|
154
|
+
contractions. Fixed-Q P projection uses float64 products on CPU and float32
|
|
155
|
+
products on CUDA.
|
|
156
|
+
|
|
157
|
+
Resident and streamed PLINK CUDA fits use float32 SQP statistics while gains
|
|
158
|
+
remain material, then switch to float64 refinement. There is no fixed float32
|
|
159
|
+
iteration cap. Tile products use float32, with float64 sums across tiles.
|
|
139
160
|
Parameters, constrained solves and likelihood checks stay in float64.
|
|
140
|
-
PLINK cuBLAS uses float32 tile products with float64 accumulation.
|
|
141
161
|
|
|
142
162
|
Genotype-likelihood fits use Q-first SQP/ZAL on both CPU and CUDA, with exact
|
|
143
|
-
EM/QN rescue and an independent EM check before convergence.
|
|
144
|
-
|
|
163
|
+
EM/QN rescue and an independent EM check before convergence. CUDA fits start
|
|
164
|
+
with float32 probabilities, derivatives and statistics in either storage mode,
|
|
145
165
|
then switch to float64 refinement. Near frequency bounds, GL probabilities
|
|
146
166
|
and derivatives use float64. cuBLAS tile sums, parameters, solves and scores stay
|
|
147
167
|
in float64.
|
|
148
|
-
CPU and CUDA start directly with SQP
|
|
168
|
+
CPU and CUDA start directly with SQP and use ZAL history depth 3.
|
|
169
|
+
`--iter` and `--tole` apply to each SQP/ZAL stage.
|
|
149
170
|
EM skips missing genotypes and exactly uniform likelihood triplets, with
|
|
150
171
|
normalization over informative entries. Nonuniform likelihoods are retained.
|
|
151
172
|
Full likelihood scores retain the constant contribution from uniform triplets.
|
|
@@ -157,13 +178,16 @@ use 4096-sample shards with a separate 4 GiB cap. Optional update caches
|
|
|
157
178
|
remain capped at 64 MiB. Input storage, factors and optimizer history are
|
|
158
179
|
additional allocations.
|
|
159
180
|
|
|
160
|
-
|
|
161
|
-
at K = 4..16 during float32 refinement
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
181
|
+
At K <= 16, CUDA fits use native kernels at K = 1..3
|
|
182
|
+
and tiled cuBLAS at K = 4..16 during float32 refinement. Resident tiles share
|
|
183
|
+
64 MiB of scratch and keep float32 copies of P and Q. At K = 8..16,
|
|
184
|
+
resident mixed fits reuse frequency scratch for cooperative float64 solves.
|
|
185
|
+
Tiles that cannot hold the solve tables use the native solve. Streamed fits keep
|
|
186
|
+
float32 copies within tiles and reuse their float64 Q-statistics buffers, with
|
|
187
|
+
up to 128 MiB of compute scratch.
|
|
188
|
+
Final refinement uses native float64 kernels, except
|
|
189
|
+
resident GL P updates at K = 8..16 with up to 1024 samples. Those share the tiled
|
|
190
|
+
cuBLAS P routine and keep combined scratch within 64 MiB.
|
|
167
191
|
Unsupervised resident PLINK fits at K = 10..16 keep the first eight iterations
|
|
168
192
|
fresh, then alternate Q-Hessian reuse during float32 refinement. The cache is
|
|
169
193
|
capped at 64 MiB. Weak cached proposals retry with fresh curvature, and
|
|
@@ -172,8 +196,8 @@ float64 refinement always uses fresh curvature.
|
|
|
172
196
|
At K > 16, CUDA uses tiled cuBLAS statistics and a cooperative active-set
|
|
173
197
|
solver for both input formats. Resident and bootstrap maps share 64 MiB of
|
|
174
198
|
scratch. Streamed maps allow up to 128 MiB of compute scratch and 512 MiB of
|
|
175
|
-
Q statistics, with free-VRAM guards.
|
|
176
|
-
|
|
199
|
+
Q statistics, with free-VRAM guards. Streamed tiles adapt to the panel width,
|
|
200
|
+
with at most 8192 rows within the same memory caps. Curvature stays fresh.
|
|
177
201
|
|
|
178
202
|
The defaults are `--threads 1`, `--seed 42`, `--iter 1000` and `--tole 1e-10`.
|
|
179
203
|
`--threads` caps CPU computation, including BLAS and GPU host copies.
|
|
@@ -333,4 +357,4 @@ fastmixture2 does not create filesystem locks or require private lock directorie
|
|
|
333
357
|
## Authors and license
|
|
334
358
|
|
|
335
359
|
Lisa Thunegard and Jonas Meisner. Developed at **MeisnerLab** and distributed
|
|
336
|
-
under the [GNU General Public License v3.0](LICENSE).
|
|
360
|
+
under the [GNU General Public License v3.0](https://github.com/MeisnerLab/fastmixture2/blob/main/LICENSE).
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# fastmixture2
|
|
2
2
|
|
|
3
3
|
[](https://github.com/MeisnerLab/fastmixture2/actions/workflows/ci.yml)
|
|
4
|
-
[](https://pypi.org/project/fastmixture2/)
|
|
5
|
+
[](https://github.com/MeisnerLab/fastmixture2/blob/main/LICENSE)
|
|
5
6
|
|
|
6
7
|
`fastmixture2` estimates ancestry proportions (`Q`) and ancestral allele
|
|
7
8
|
frequencies (`P`) by maximum likelihood. It reads SNP-major PLINK genotypes
|
|
8
9
|
or ANGSD Beagle genotype likelihoods. Unsupervised initialization uses SVD/ALS
|
|
9
|
-
for K > 1
|
|
10
|
-
on NVIDIA CUDA.
|
|
10
|
+
for K > 1, with subset likelihood refinement for large panels.
|
|
11
|
+
All modes use safeguarded SQP/ZAL updates on CPU or, with `--gpu`, on NVIDIA CUDA.
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
|
|
@@ -27,7 +28,8 @@ Source builds need a C compiler with OpenMP. On macOS, install OpenMP with
|
|
|
27
28
|
`brew install libomp`. On HPC, build on the compute-node type used for your
|
|
28
29
|
analyses.
|
|
29
30
|
|
|
30
|
-
With Conda, the [CPU](environment-cpu.yml)
|
|
31
|
+
With Conda, the [CPU](https://github.com/MeisnerLab/fastmixture2/blob/main/environment-cpu.yml)
|
|
32
|
+
and [GPU](https://github.com/MeisnerLab/fastmixture2/blob/main/environment-gpu.yml)
|
|
31
33
|
environments retain native CPU tuning. Run from the cloned repository:
|
|
32
34
|
|
|
33
35
|
```bash
|
|
@@ -38,7 +40,7 @@ conda activate fastmixture2-cpu
|
|
|
38
40
|
For GPU use, select `environment-gpu.yml` and activate `fastmixture2-gpu`.
|
|
39
41
|
|
|
40
42
|
PyPI wheels cover Linux (glibc) and macOS 14 or newer, on x86-64 and ARM64.
|
|
41
|
-
They
|
|
43
|
+
They use AVX2 on supported x86-64 CPUs and NEON on ARM64, including Apple Silicon:
|
|
42
44
|
|
|
43
45
|
```bash
|
|
44
46
|
python -m pip install fastmixture2
|
|
@@ -101,20 +103,39 @@ fastmixture2 --bfile cohort --K 5 --threads 8 --gpu --out cohort.gpu
|
|
|
101
103
|
CPU and CUDA support `1 <= K <= 128` for both input formats in all modes.
|
|
102
104
|
CUDA keeps input data on the GPU when they fit and streams in blocks otherwise.
|
|
103
105
|
Small CPU/GPU differences can arise from floating-point arithmetic.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
then
|
|
106
|
+
|
|
107
|
+
At K > 1, unsupervised initialization uses 10 SVD power iterations on all SNPs
|
|
108
|
+
up to 50,000, or a genome-wide 50,000-SNP subset otherwise. Larger panels refine
|
|
109
|
+
subset Q/P with SQP/ZAL, then fit full-marker P by least squares at fixed Q and
|
|
110
|
+
retain the refined subset rows. This applies to both input formats, including
|
|
111
|
+
missing genotypes.
|
|
112
|
+
Panels up to 50,000 SNPs proceed directly from SVD/ALS to full-data refinement,
|
|
113
|
+
without a duplicate subset fit or projection. For PLINK, subset refinement is
|
|
114
|
+
skipped if any sample has no observed subset genotypes. Exact CV folds and
|
|
115
|
+
`--iter 0` retain SVD/ALS without subset likelihood refinement.
|
|
116
|
+
|
|
117
|
+
Subsets exceeding 512 MiB on CPU or 256 MiB on CUDA are built in bounded blocks
|
|
118
|
+
into a temporary memory-mapped file. CUDA streams the subset when it does not
|
|
119
|
+
fit in VRAM. Temporary files use `TMPDIR`, which can point to disk-backed scratch
|
|
120
|
+
storage.
|
|
121
|
+
|
|
122
|
+
CUDA SVD starts at 256 samples. Both devices use CPU ALS with float64
|
|
123
|
+
contractions. Fixed-Q P projection uses float64 products on CPU and float32
|
|
124
|
+
products on CUDA.
|
|
125
|
+
|
|
126
|
+
Resident and streamed PLINK CUDA fits use float32 SQP statistics while gains
|
|
127
|
+
remain material, then switch to float64 refinement. There is no fixed float32
|
|
128
|
+
iteration cap. Tile products use float32, with float64 sums across tiles.
|
|
108
129
|
Parameters, constrained solves and likelihood checks stay in float64.
|
|
109
|
-
PLINK cuBLAS uses float32 tile products with float64 accumulation.
|
|
110
130
|
|
|
111
131
|
Genotype-likelihood fits use Q-first SQP/ZAL on both CPU and CUDA, with exact
|
|
112
|
-
EM/QN rescue and an independent EM check before convergence.
|
|
113
|
-
|
|
132
|
+
EM/QN rescue and an independent EM check before convergence. CUDA fits start
|
|
133
|
+
with float32 probabilities, derivatives and statistics in either storage mode,
|
|
114
134
|
then switch to float64 refinement. Near frequency bounds, GL probabilities
|
|
115
135
|
and derivatives use float64. cuBLAS tile sums, parameters, solves and scores stay
|
|
116
136
|
in float64.
|
|
117
|
-
CPU and CUDA start directly with SQP
|
|
137
|
+
CPU and CUDA start directly with SQP and use ZAL history depth 3.
|
|
138
|
+
`--iter` and `--tole` apply to each SQP/ZAL stage.
|
|
118
139
|
EM skips missing genotypes and exactly uniform likelihood triplets, with
|
|
119
140
|
normalization over informative entries. Nonuniform likelihoods are retained.
|
|
120
141
|
Full likelihood scores retain the constant contribution from uniform triplets.
|
|
@@ -126,13 +147,16 @@ use 4096-sample shards with a separate 4 GiB cap. Optional update caches
|
|
|
126
147
|
remain capped at 64 MiB. Input storage, factors and optimizer history are
|
|
127
148
|
additional allocations.
|
|
128
149
|
|
|
129
|
-
|
|
130
|
-
at K = 4..16 during float32 refinement
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
At K <= 16, CUDA fits use native kernels at K = 1..3
|
|
151
|
+
and tiled cuBLAS at K = 4..16 during float32 refinement. Resident tiles share
|
|
152
|
+
64 MiB of scratch and keep float32 copies of P and Q. At K = 8..16,
|
|
153
|
+
resident mixed fits reuse frequency scratch for cooperative float64 solves.
|
|
154
|
+
Tiles that cannot hold the solve tables use the native solve. Streamed fits keep
|
|
155
|
+
float32 copies within tiles and reuse their float64 Q-statistics buffers, with
|
|
156
|
+
up to 128 MiB of compute scratch.
|
|
157
|
+
Final refinement uses native float64 kernels, except
|
|
158
|
+
resident GL P updates at K = 8..16 with up to 1024 samples. Those share the tiled
|
|
159
|
+
cuBLAS P routine and keep combined scratch within 64 MiB.
|
|
136
160
|
Unsupervised resident PLINK fits at K = 10..16 keep the first eight iterations
|
|
137
161
|
fresh, then alternate Q-Hessian reuse during float32 refinement. The cache is
|
|
138
162
|
capped at 64 MiB. Weak cached proposals retry with fresh curvature, and
|
|
@@ -141,8 +165,8 @@ float64 refinement always uses fresh curvature.
|
|
|
141
165
|
At K > 16, CUDA uses tiled cuBLAS statistics and a cooperative active-set
|
|
142
166
|
solver for both input formats. Resident and bootstrap maps share 64 MiB of
|
|
143
167
|
scratch. Streamed maps allow up to 128 MiB of compute scratch and 512 MiB of
|
|
144
|
-
Q statistics, with free-VRAM guards.
|
|
145
|
-
|
|
168
|
+
Q statistics, with free-VRAM guards. Streamed tiles adapt to the panel width,
|
|
169
|
+
with at most 8192 rows within the same memory caps. Curvature stays fresh.
|
|
146
170
|
|
|
147
171
|
The defaults are `--threads 1`, `--seed 42`, `--iter 1000` and `--tole 1e-10`.
|
|
148
172
|
`--threads` caps CPU computation, including BLAS and GPU host copies.
|
|
@@ -302,4 +326,4 @@ fastmixture2 does not create filesystem locks or require private lock directorie
|
|
|
302
326
|
## Authors and license
|
|
303
327
|
|
|
304
328
|
Lisa Thunegard and Jonas Meisner. Developed at **MeisnerLab** and distributed
|
|
305
|
-
under the [GNU General Public License v3.0](LICENSE).
|
|
329
|
+
under the [GNU General Public License v3.0](https://github.com/MeisnerLab/fastmixture2/blob/main/LICENSE).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0.4"
|
|
@@ -14,9 +14,9 @@ LIKELIHOOD_CACHE_HEADER_BYTES = 256
|
|
|
14
14
|
LIKELIHOOD_CACHE_VERSION = 5
|
|
15
15
|
LIKELIHOOD_FREQUENCY_VERSION = 2
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
INITIALIZATION_MARKERS =
|
|
19
|
-
SVD_POWER_ITERATIONS =
|
|
17
|
+
# Initialization
|
|
18
|
+
INITIALIZATION_MARKERS = 50_000
|
|
19
|
+
SVD_POWER_ITERATIONS = 10
|
|
20
20
|
SVD_CHUNK_MARKERS = 4_096
|
|
21
21
|
SVD_WORKSPACE_BYTES = 512 << 20
|
|
22
22
|
GPU_SVD_WORKSPACE_BYTES = 256 << 20
|
|
@@ -1244,15 +1244,17 @@ cpdef int accelPacked(
|
|
|
1244
1244
|
return 0
|
|
1245
1245
|
|
|
1246
1246
|
|
|
1247
|
-
### Form one weighted packed marker-bootstrap EM map
|
|
1248
|
-
|
|
1247
|
+
### Form one multiplicity-weighted packed marker-bootstrap EM map
|
|
1248
|
+
cpdef int batchPackedW(
|
|
1249
1249
|
const u8[:, ::1] B, const f64[:, ::1] P,
|
|
1250
1250
|
f64[:, ::1] P1, const f64[:, ::1] Q,
|
|
1251
|
-
f64[:, ::1] T, const u32[::1] s, const u32
|
|
1252
|
-
const Py_ssize_t N,
|
|
1253
|
-
|
|
1251
|
+
f64[:, ::1] T, const u32[::1] s, const u32[::1] w,
|
|
1252
|
+
const Py_ssize_t N, Py_ssize_t fold=-1,
|
|
1253
|
+
Py_ssize_t folds=1, uint64_t seed=0
|
|
1254
1254
|
) except -1 nogil:
|
|
1255
1255
|
cdef:
|
|
1256
|
+
bint masked = fold >= 0
|
|
1257
|
+
const u32* wt = &w[0]
|
|
1256
1258
|
u8* g_thr
|
|
1257
1259
|
u8* g_all
|
|
1258
1260
|
const f64* p
|
|
@@ -1290,7 +1292,7 @@ cdef int _batchPacked(
|
|
|
1290
1292
|
for j in prange(M, schedule="static"):
|
|
1291
1293
|
marker = s[j]
|
|
1292
1294
|
p = &P[marker, 0]
|
|
1293
|
-
if
|
|
1295
|
+
if wt[j] == 0:
|
|
1294
1296
|
for k in range(K):
|
|
1295
1297
|
P1[marker, k] = p[k]
|
|
1296
1298
|
continue
|
|
@@ -1302,7 +1304,7 @@ cdef int _batchPacked(
|
|
|
1302
1304
|
else:
|
|
1303
1305
|
_unpackPackedRow(&B[marker, 0], g_thr, N)
|
|
1304
1306
|
if not _specializedEmRowW(
|
|
1305
|
-
g_thr, p, &Q[0, 0], &P1[marker, 0], q_thr,
|
|
1307
|
+
g_thr, p, &Q[0, 0], &P1[marker, 0], q_thr, wt[j], N, K
|
|
1306
1308
|
):
|
|
1307
1309
|
for i in range(N):
|
|
1308
1310
|
if g_thr[i] == 9:
|
|
@@ -1311,7 +1313,7 @@ cdef int _batchPacked(
|
|
|
1311
1313
|
h = _computeH(p, q, K)
|
|
1312
1314
|
_innerJW(
|
|
1313
1315
|
p, q, &p_thr[0], &p_thr[K], &q_thr[i * K],
|
|
1314
|
-
g_thr[i],
|
|
1316
|
+
g_thr[i], wt[j], K, h
|
|
1315
1317
|
)
|
|
1316
1318
|
_outerAccelP(p, &P1[marker, 0], &p_thr[0], &p_thr[K], K)
|
|
1317
1319
|
for x in prange(L, schedule="static"):
|
|
@@ -1323,17 +1325,6 @@ cdef int _batchPacked(
|
|
|
1323
1325
|
return 0
|
|
1324
1326
|
|
|
1325
1327
|
|
|
1326
|
-
### Form one multiplicity-weighted packed marker-bootstrap EM map
|
|
1327
|
-
cpdef int batchPackedW(
|
|
1328
|
-
const u8[:, ::1] B, const f64[:, ::1] P, f64[:, ::1] P1,
|
|
1329
|
-
const f64[:, ::1] Q, f64[:, ::1] T,
|
|
1330
|
-
const u32[::1] s, const u32[::1] w,
|
|
1331
|
-
const Py_ssize_t N, Py_ssize_t fold=-1,
|
|
1332
|
-
Py_ssize_t folds=1, uint64_t seed=0
|
|
1333
|
-
) except -1 nogil:
|
|
1334
|
-
return _batchPacked(B, P, P1, Q, T, s, &w[0], N, fold >= 0, fold, folds, seed)
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
1328
|
### Form one packed fixed-P Q map
|
|
1338
1329
|
cpdef int stepQPacked(
|
|
1339
1330
|
const u8[:, ::1] B, const f64[:, ::1] P,
|
|
@@ -805,6 +805,13 @@ def _run(args, stack):
|
|
|
805
805
|
else:
|
|
806
806
|
boot_h, b_chr = utils.bootBlock(args.bfile, M, args.bootstrap_block)
|
|
807
807
|
|
|
808
|
+
run = {
|
|
809
|
+
"iter": args.iter,
|
|
810
|
+
"tole": args.tole,
|
|
811
|
+
"check": check,
|
|
812
|
+
"gpu": use_gpu,
|
|
813
|
+
"log": runtime.append,
|
|
814
|
+
}
|
|
808
815
|
print("\nInitialization:")
|
|
809
816
|
resumed = pops = y = None
|
|
810
817
|
if args.resume is not None:
|
|
@@ -861,6 +868,7 @@ def _run(args, stack):
|
|
|
861
868
|
P1, Q = resumed[:2]
|
|
862
869
|
if P1 is not None and not np.allclose(P1, P0, atol=1e-12, rtol=0.0):
|
|
863
870
|
raise ValueError("Checkpoint frequencies do not match --projection")
|
|
871
|
+
del P1
|
|
864
872
|
P = P0
|
|
865
873
|
del P0
|
|
866
874
|
sec = time() - ts
|
|
@@ -893,10 +901,12 @@ def _run(args, stack):
|
|
|
893
901
|
elif use_gpu:
|
|
894
902
|
from fastmixture2 import gpu
|
|
895
903
|
|
|
896
|
-
P, Q = gpu.initializeUnsupervised(G, args.K, rng)
|
|
904
|
+
P, Q = gpu.initializeUnsupervised(G, args.K, rng, run=run)
|
|
897
905
|
else:
|
|
898
|
-
P, Q = utils.initializeUnsupervised(G, args.K, rng)
|
|
906
|
+
P, Q = utils.initializeUnsupervised(G, args.K, rng, run=run)
|
|
899
907
|
sec = time() - ts
|
|
908
|
+
if "init" in run:
|
|
909
|
+
label = "SVD/ALS and subset refinement"
|
|
900
910
|
functions.printTiming(f"{label}.", sec, replace=True)
|
|
901
911
|
runtime.append(f"{label}: {sec:.1f} s")
|
|
902
912
|
else:
|
|
@@ -909,14 +919,6 @@ def _run(args, stack):
|
|
|
909
919
|
if inputKey(args) != src_key:
|
|
910
920
|
raise ValueError("Analysis inputs changed while reading")
|
|
911
921
|
|
|
912
|
-
# Build the optimizer settings
|
|
913
|
-
run = {
|
|
914
|
-
"iter": args.iter,
|
|
915
|
-
"tole": args.tole,
|
|
916
|
-
"check": check,
|
|
917
|
-
"gpu": use_gpu,
|
|
918
|
-
"log": runtime.append,
|
|
919
|
-
}
|
|
920
922
|
if resumed is not None:
|
|
921
923
|
if not use_gpu:
|
|
922
924
|
like = functions._loglike(G, q_nrm)
|
|
@@ -929,6 +931,7 @@ def _run(args, stack):
|
|
|
929
931
|
|
|
930
932
|
# CUDA scores resumed estimates after their single host-to-device transfer
|
|
931
933
|
run["off"] = resumed[3]
|
|
934
|
+
del resumed
|
|
932
935
|
ckpt = args.checkpoint or args.resume
|
|
933
936
|
if ckpt is not None:
|
|
934
937
|
### Persist the latest accepted optimizer state
|