diff --git a/iprbench/main.py b/iprbench/main.py index 50d4b0c..202e932 100644 --- a/iprbench/main.py +++ b/iprbench/main.py @@ -1,7 +1,8 @@ from .core import BenchmarkId, IBenchmark, ResultsDbFactory from .benchmarks.hibench import HiBench from .benchmarks.mamul1 import MaMul1 -from .resultsdb.tsvresultsdb import TsvResultsDbCreator +from .resultsdb.tsvresultsdb import TsvResultsDbCreator +from .resultsdb.sqlresultsdb import SqlResultsDbCreator from .util import Singleton from .autoparams import MeasurementTime import logging @@ -52,6 +53,7 @@ def main(): results_dir = args.results_dir ResultsDbFactory().register_resultsdb_creator(TsvResultsDbCreator()) + ResultsDbFactory().register_resultsdb_creator(SqlResultsDbCreator()) resultsdb_params = json.loads(args.resultsdb_params) results_db = ResultsDbFactory().create_resultsdb(resultsdb_params['type'], resultsdb_params) diff --git a/iprbench/resultsdb/sqlresultsdb.py b/iprbench/resultsdb/sqlresultsdb.py new file mode 100644 index 0000000..144da8d --- /dev/null +++ b/iprbench/resultsdb/sqlresultsdb.py @@ -0,0 +1,73 @@ +from typing import List +import logging +from pathlib import Path +from cocluto.SimpaDbUtil import ISqlDatabaseBackend, SqliteDb, SqlTableField +from ..core import IResultsDb, IResultsTable, BenchmarkParamValues, IBenchmark, IResultsDbCreator, ResultsDbParams, BenchParam + + +class SqlResultsTable(IResultsTable): + sql_backend: ISqlDatabaseBackend + + def __init__(self, benchmark: IBenchmark, results_db: 'SqlResultsDb', sql_backend: ISqlDatabaseBackend): + self.sql_backend = sql_backend + super().__init__(results_db, benchmark) + + def add_benchmark(self, benchmark_record: BenchmarkParamValues): + """adds a benchmark record to this table + + a benchmark record represents a row of values in a benchmark results table; it contains the benchmark's results, along with the configuration parameters and the BenchmarkAutoParams. For exemple { 'measurement_time': datetime.(2024, 10, 24, 16, 34, 41), 'cpu': 'intel_xeon_6348r', 'matrix_size': 1024, 'duration': 0.522} + """ + table_name = self.get_sql_table_name() + params = self.get_params() + if not self.sql_backend.table_exists(table_name): + logging.debug('creating table %s because it doesn\'t already exist', table_name) + + fields: List[SqlTableField] = [] + + index_name = 'measure_id' + fields.append(SqlTableField(index_name, SqlTableField.Type.FIELD_TYPE_INT, 'unique identifier of the measurement', is_autoinc_index=True)) + for param in params: + param: BenchParam + sql_field_type = { + BenchParam.Type.PARAM_TYPE_FLOAT: SqlTableField.Type.FIELD_TYPE_FLOAT, + BenchParam.Type.PARAM_TYPE_INT: SqlTableField.Type.FIELD_TYPE_FLOAT, + BenchParam.Type.PARAM_TYPE_STRING: SqlTableField.Type.FIELD_TYPE_FLOAT, + BenchParam.Type.PARAM_TYPE_TIME: SqlTableField.Type.FIELD_TYPE_FLOAT, + }[param.param_type] + fields.append(SqlTableField(param.name, sql_field_type, param.description)) + self.sql_backend.create_table(table_name, fields) + assert self.sql_backend.table_exists(table_name) + # "use iprbenchs; insert into $strTableName(measure_time, computer_name, num_cpus, cpu_model, computer_id, matrix_size, mkl_version, bench_duration, num_mmul, mmul_duration, gflops) values('$strNow', '$(Util_getMyHostName)', '$(Util_getNumCpus)', '$(Util_getCpuName)', '$(Util_getHardwareSerialNumber)', '$iMatrixSize', '$strMklVersion', '$fBenchDuration', '$iNumLoops', '$fMeanMMulDuration', '$fGflops');" + param_names = [] + param_values = [] + for param in params: + param_names.append(param.name) + param_values.append(f"'{str(benchmark_record[param.name])}'") + logging.debug('param %s = \'%s\'', param.name, str(benchmark_record[param.name])) + sql_add_row_command = f"INSERT INTO {table_name} ({', '.join(param_names)}) values({', '.join(param_values)});" + _ = self.sql_backend.query(sql_add_row_command) + + def get_sql_table_name(self) -> str: + return self.benchmark.bench_id + + +class SqlResultsDb(IResultsDb): + sql_backend: ISqlDatabaseBackend + + def __init__(self, sql_backend: ISqlDatabaseBackend): + self.sql_backend = sql_backend + super().__init__() + + def get_table(self, benchmark: IBenchmark) -> IResultsTable: + table = SqlResultsTable(benchmark, self, self.sql_backend) + return table + + +class SqlResultsDbCreator(IResultsDbCreator): + + def __init__(self): + super().__init__('sql-database') + + def create_resultsdb(self, resultsdb_config: ResultsDbParams) -> IResultsDb: + sql_backend = SqliteDb(Path(resultsdb_config['sqlite_file_path'])) + return SqlResultsDb(sql_backend) diff --git a/pyproject.toml b/pyproject.toml index 8729a23..e442597 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,9 +13,9 @@ dependencies = [ "pandas", "matplotlib", "sqlalchemy", -# "cocluto >= 1.2" + "cocluto >= 1.4", # "cocluto@git+https://git.ipr.univ-rennes.fr/cellinfo/cocluto" - "starbench >= 1.0.1" + "starbench >= 1.0.1" # "starbench@git+https://github.com/g-raffy/starbench" ] requires-python = ">= 3.8" diff --git a/test/test_iprbench.py b/test/test_iprbench.py index 87ec39f..67b904f 100644 --- a/test/test_iprbench.py +++ b/test/test_iprbench.py @@ -35,6 +35,22 @@ class IprBenchTestCase(unittest.TestCase): command = f'iprbench-run --benchmark-id \'mamul1\' --config \'{json.dumps(config)}\' --results-dir {results_dir} --resultsdb-params \'{json.dumps(resultsdb_params)}\'' subprocess.run(command, shell=True, check=True, executable='/bin/bash') + def test_sqlite(self): + logging.info('test_sqlite') + results_dir = Path('/tmp/mamul1_out') + config = { + 'compiler_id': 'gfortran', + 'matrix_size': 1024, + 'num_loops': 10, + 'num_cores': 2 + } + resultsdb_params = { + 'type': 'sql-database', + 'sqlite_file_path': '/tmp/iprbench_results.sql' + } + command = f'iprbench-run --benchmark-id \'mamul1\' --config \'{json.dumps(config)}\' --results-dir {results_dir} --resultsdb-params \'{json.dumps(resultsdb_params)}\'' + subprocess.run(command, shell=True, check=True, executable='/bin/bash') + def test_iprbench_hibench(self): logging.info('test_iprbench_hibench') results_dir = Path('/tmp/hibench_out')