Skip to content

Commit 01bf46e

Browse files
committed
[query] Various Benchmark Suite Improvements
1 parent fc7b02f commit 01bf46e

14 files changed

+490
-318
lines changed

hail/python/benchmark/conftest.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
def pytest_addoption(parser):
1313
parser.addoption("--log", type=str, help='Log file path', default=None)
1414
parser.addoption("--output", type=str, help="Output file path.", default=None)
15-
parser.addoption("--data-dir", type=str, help="Data directory.", default=None)
15+
parser.addoption("--data-dir", type=str, help="Data directory.", default=os.getenv('HAIL_BENCHMARK_DIR'))
1616
parser.addoption('--iterations', type=int, help='override number of iterations for all benchmarks', default=None)
1717
parser.addoption('--cores', type=int, help='Number of cores to use.', default=1)
1818
parser.addoption(
@@ -23,36 +23,36 @@ def pytest_addoption(parser):
2323
const='cpu',
2424
default=None,
2525
)
26-
parser.addoption('--profiler-path', type=str, help='path to aysnc profiler', default=None)
26+
parser.addoption(
27+
'--max-duration',
28+
type=int,
29+
help='Maximum permitted duration for any benchmark trial in seconds, not to be confused with pytest-timeout',
30+
default=200,
31+
)
32+
parser.addoption('--max-failures', type=int, help='Stop benchmarking item after this many failures', default=3)
33+
parser.addoption(
34+
'--profiler-path', type=str, help='path to aysnc profiler', default=os.getenv('ASYNC_PROFILER_HOME')
35+
)
2736
parser.addoption('--profiler-fmt', choices=['html', 'flame', 'jfr'], help='Choose profiler output.', default='html')
2837

2938

30-
def run_config_from_pytest_config(pytest_config):
31-
return type(
32-
'RunConfig',
33-
(object,),
34-
{
35-
**{
36-
flag: pytest_config.getoption(flag) or default
37-
for flag, default in [
38-
('log', None),
39-
('output', None),
40-
('cores', 1),
41-
('data_dir', os.getenv('HAIL_BENCHMARK_DIR')),
42-
('iterations', None),
43-
('profile', None),
44-
('profiler_path', os.getenv('ASYNC_PROFILER_HOME')),
45-
('profiler_fmt', None),
46-
]
47-
},
48-
'verbose': pytest_config.getoption('verbose') > 0,
49-
'quiet': pytest_config.getoption('verbose') < 0,
50-
'timeout': int(pytest_config.getoption('timeout') or 1800),
51-
},
39+
@pytest.hookimpl
40+
def pytest_configure(config):
41+
init_logging(file=config.getoption('log'))
42+
43+
44+
@pytest.hookimpl(tryfirst=True)
45+
def pytest_collection_modifyitems(config, items):
46+
max_duration = config.getoption('max_duration')
47+
48+
xfail = pytest.mark.xfail(
49+
raises=TimeoutError,
50+
reason=f'Runtime exceeds maximum permitted duration of {max_duration}s',
5251
)
5352

53+
for item in items:
54+
if (xtimeout := item.get_closest_marker('xtimeout')) is None:
55+
continue
5456

55-
@pytest.hookimpl
56-
def pytest_configure(config):
57-
config.run_config = run_config_from_pytest_config(config)
58-
init_logging(file=config.run_config.log)
57+
if len(xtimeout.args) == 0 or (len(xtimeout.args) == 1 and xtimeout.args[0] >= max_duration):
58+
item.add_marker(xfail)

hail/python/benchmark/hail/benchmark_combiner.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
import hail as hl
6-
from benchmark.tools import benchmark, chunk
6+
from benchmark.tools import chunk
77
from hail.vds.combiner import combine_variant_datasets, new_combiner, transform_gvcf
88

99
COMBINE_GVCF_MAX = 100
@@ -14,7 +14,8 @@ def import_vcf(path):
1414
return hl.import_vcf(str(path), reference_genome='GRCh38', force=True)
1515

1616

17-
@benchmark()
17+
@pytest.mark.benchmark()
18+
@pytest.mark.xfail(raises=hl.utils.java.FatalError, reason='??')
1819
@with_flags(no_ir_logging='1')
1920
def benchmark_compile_2k_merge(empty_gvcf, tmp_path):
2021
vcf = import_vcf(empty_gvcf)
@@ -23,29 +24,30 @@ def benchmark_compile_2k_merge(empty_gvcf, tmp_path):
2324
hl.vds.write_variant_datasets(combined, str(tmp_path / 'combiner-multi-write'), overwrite=True)
2425

2526

26-
@benchmark()
27+
@pytest.mark.benchmark()
28+
@pytest.mark.xtimeout(270)
2729
def benchmark_python_only_10k_transform(empty_gvcf):
2830
for vcf in [import_vcf(empty_gvcf)] * 10_000:
2931
transform_gvcf(vcf, [])
3032

3133

32-
@benchmark()
34+
@pytest.mark.benchmark()
3335
def benchmark_python_only_10k_combine(empty_gvcf):
3436
vcf = import_vcf(empty_gvcf)
3537
mt = transform_gvcf(vcf, [])
3638
for mts in chunk(COMBINE_GVCF_MAX, [mt] * 10_000):
3739
combine_variant_datasets(mts)
3840

3941

40-
@benchmark()
42+
@pytest.mark.benchmark()
4143
def benchmark_import_and_transform_gvcf(single_gvcf):
4244
mt = import_vcf(single_gvcf)
4345
vds = transform_gvcf(mt, [])
4446
vds.reference_data._force_count_rows()
4547
vds.variant_data._force_count_rows()
4648

4749

48-
@benchmark()
50+
@pytest.mark.benchmark()
4951
def benchmark_import_gvcf_force_count(single_gvcf):
5052
mt = import_vcf(single_gvcf)
5153
mt._force_count_rows()
@@ -60,14 +62,15 @@ def tmp_and_output_paths(tmp_path):
6062
return (tmp, output)
6163

6264

63-
@benchmark()
65+
@pytest.mark.benchmark()
66+
@pytest.mark.xtimeout(180)
6467
def benchmark_vds_combiner_chr22(chr22_gvcfs, tmp_and_output_paths):
6568
parts = hl.eval([hl.parse_locus_interval('chr22:start-end', reference_genome='GRCh38')])
66-
69+
tmp, output = tmp_and_output_paths
6770
combiner = new_combiner(
68-
output_path=str(tmp_and_output_paths[0]),
71+
output_path=str(output),
6972
intervals=parts,
70-
temp_path=str(tmp_and_output_paths[1]),
73+
temp_path=str(tmp),
7174
gvcf_paths=[str(path) for path in chr22_gvcfs],
7275
reference_genome='GRCh38',
7376
branch_factor=16,

hail/python/benchmark/hail/benchmark_linalg.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,52 @@
1+
import pytest
2+
13
import hail as hl
2-
from benchmark.tools import benchmark
34

45

5-
@benchmark()
6+
@pytest.mark.benchmark()
7+
@pytest.mark.xtimeout
68
def benchmark_block_matrix_nested_multiply(tmp_path):
79
bm = hl.linalg.BlockMatrix.random(8 * 1024, 8 * 1024)
810
bm = bm.checkpoint(str(tmp_path / 'checkpoint.mt'))
911
bm = (bm @ bm) @ bm @ bm @ (bm @ bm)
1012
bm.write(str(tmp_path / 'result.mt'), overwrite=True)
1113

1214

13-
@benchmark()
15+
@pytest.mark.benchmark()
1416
def benchmark_make_ndarray():
1517
ht = hl.utils.range_table(200_000)
1618
ht = ht.annotate(x=hl.nd.array(hl.range(ht.idx)))
1719
ht._force_count()
1820

1921

20-
@benchmark()
22+
@pytest.mark.benchmark()
2123
def benchmark_ndarray_addition():
2224
arr = hl.nd.ones((1024, 1024))
2325
hl.eval(arr + arr)
2426

2527

26-
@benchmark()
28+
@pytest.mark.benchmark()
2729
def benchmark_ndarray_matmul_int64():
2830
arr = hl.nd.arange(1024 * 1024).map(hl.int64).reshape((1024, 1024))
2931
hl.eval(arr @ arr)
3032

3133

32-
@benchmark()
34+
@pytest.mark.benchmark()
3335
def benchmark_ndarray_matmul_float64():
3436
arr = hl.nd.arange(1024 * 1024).map(hl.float64).reshape((1024, 1024))
3537
hl.eval(arr @ arr)
3638

3739

38-
@benchmark()
40+
@pytest.mark.benchmark()
41+
@pytest.mark.xtimeout(200)
3942
def benchmark_blockmatrix_write_from_entry_expr_range_mt(tmp_path):
4043
mt = hl.utils.range_matrix_table(40_000, 40_000, n_partitions=4)
4144
path = str(tmp_path / 'result.bm')
4245
hl.linalg.BlockMatrix.write_from_entry_expr(mt.row_idx + mt.col_idx, path)
4346

4447

45-
@benchmark()
48+
@pytest.mark.benchmark()
49+
@pytest.mark.xtimeout(700)
4650
def benchmark_blockmatrix_write_from_entry_expr_range_mt_standardize(tmp_path):
4751
mt = hl.utils.range_matrix_table(40_000, 40_000, n_partitions=4)
4852
path = str(tmp_path / 'result.bm')
@@ -51,20 +55,22 @@ def benchmark_blockmatrix_write_from_entry_expr_range_mt_standardize(tmp_path):
5155
)
5256

5357

54-
@benchmark()
58+
@pytest.mark.benchmark()
5559
def benchmark_sum_table_of_ndarrays():
5660
ht = hl.utils.range_table(400).annotate(nd=hl.nd.ones((4096, 4096)))
5761
ht.aggregate(hl.agg.ndarray_sum(ht.nd))
5862

5963

60-
@benchmark()
64+
@pytest.mark.benchmark()
65+
@pytest.mark.xtimeout(250)
6166
def benchmark_block_matrix_to_matrix_table_row_major():
6267
mt = hl.utils.range_matrix_table(20_000, 20_000, n_partitions=4)
6368
bm = hl.linalg.BlockMatrix.from_entry_expr(mt.row_idx + mt.col_idx)
6469
bm.to_matrix_table_row_major()._force_count_rows()
6570

6671

67-
@benchmark()
72+
@pytest.mark.benchmark()
73+
@pytest.mark.xtimeout
6874
def benchmark_king(tmp_path):
6975
mt = hl.balding_nichols_model(6, n_variants=10000, n_samples=4096)
7076
path = str(tmp_path / 'result.mt')

0 commit comments

Comments
 (0)