Added partial support for synthetic matrices
This commit is contained in:
parent
6bf301e9b7
commit
66b0699fa8
@ -16,7 +16,7 @@ class Stat(Enum):
|
||||
MATRIX_SHAPE = 'matrix shape'
|
||||
MATRIX_SIZE = 'matrix size'
|
||||
MATRIX_NNZ = 'matrix nnz'
|
||||
MATRIX_DENSITY = 'matrix density %'
|
||||
MATRIX_DENSITY = 'matrix density'
|
||||
|
||||
#POWER_BEFORE = 'power before'
|
||||
#POWER = 'power'
|
||||
@ -65,6 +65,10 @@ class Stat(Enum):
|
||||
L2D_CACHE_MISS_RATE = 'L2D cache miss rate'
|
||||
LL_CACHE_MISS_RATE = 'LL cache miss rate'
|
||||
|
||||
class Format(Enum):
|
||||
CSR = 'csr'
|
||||
COO = 'coo'
|
||||
|
||||
class Cpu(Enum):
|
||||
#ALTRA = altra_names
|
||||
#XEON = xeon_names
|
||||
|
@ -1,4 +1,4 @@
|
||||
from data_stat import Cpu
|
||||
from data_stat import Cpu, Format
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
@ -10,7 +10,10 @@ parser = argparse.ArgumentParser()
|
||||
parser.add_argument('cpu', choices=[x.name.lower() for x in Cpu])
|
||||
parser.add_argument('output_dir')
|
||||
parser.add_argument('matrix_dir')
|
||||
parser.add_argument('iterations', type=int)
|
||||
parser.add_argument('format', type=str,
|
||||
choices=[fmt.name.lower() for fmt in Format])
|
||||
parser.add_argument('base_iterations', type=int)
|
||||
parser.add_argument('min_time_s', type=int)
|
||||
parser.add_argument('baseline_time_s', type=int)
|
||||
parser.add_argument('baseline_delay_s', type=int)
|
||||
parser.add_argument('--perf', action='store_const', const='--perf')
|
||||
@ -18,6 +21,7 @@ parser.add_argument('--power', action='store_const', const='--power')
|
||||
parser.add_argument('--distribute', action='store_true')
|
||||
args = parser.parse_args()
|
||||
args.cpu = Cpu[args.cpu.upper()]
|
||||
args.format = Format[args.format.upper()]
|
||||
|
||||
srun_args = {
|
||||
Cpu.ALTRA: [
|
||||
@ -40,18 +44,29 @@ srun_args = {
|
||||
'--cpus-per-task', '16',
|
||||
'--ntasks-per-node', '1',
|
||||
'--prefer', 'EPYC-7313P'
|
||||
],
|
||||
Cpu.XEON_4216: [
|
||||
'--account', 'nexus',
|
||||
'--partition', 'tron',
|
||||
'--qos', 'tron-exempt',
|
||||
'--cpus-per-task', '32',
|
||||
'--ntasks-per-node', '1',
|
||||
'--prefer', 'Xeon,4216'
|
||||
]
|
||||
}
|
||||
python = {
|
||||
Cpu.ALTRA: 'python3',
|
||||
Cpu.EPYC_7313P: 'python3.11'
|
||||
Cpu.EPYC_7313P: 'python3.11',
|
||||
Cpu.XEON_4216: 'python3.11'
|
||||
}
|
||||
|
||||
def srun(srun_args_list: list, run_args, matrix_file: str) -> list:
|
||||
run_args_list = [
|
||||
args.cpu.name.lower(),
|
||||
matrix_file,
|
||||
str(args.iterations),
|
||||
args.format.name.lower(),
|
||||
str(args.base_iterations),
|
||||
str(args.min_time_s),
|
||||
str(args.baseline_time_s),
|
||||
str(args.baseline_delay_s)]
|
||||
if args.perf is not None:
|
||||
@ -74,10 +89,10 @@ for i, matrix in enumerate(glob.glob(f'{args.matrix_dir.rstrip("/")}/*.mtx')):
|
||||
|
||||
output_filename = '_'.join([
|
||||
args.cpu.name.lower(),
|
||||
str(args.min_time_s),
|
||||
str(args.baseline_time_s),
|
||||
str(args.baseline_delay_s),
|
||||
os.path.splitext(os.path.basename(matrix))[0],
|
||||
str(args.iterations)])
|
||||
os.path.splitext(os.path.basename(matrix))[0]])
|
||||
|
||||
json_filepath = f'{args.output_dir.rstrip("/")}/{output_filename}.json'
|
||||
raw_filepath = f'{args.output_dir.rstrip("/")}/{output_filename}.output'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import data_stat
|
||||
from data_stat import Stat, Cpu
|
||||
from data_stat import Stat, Cpu, Format
|
||||
|
||||
import argparse
|
||||
import os, sys
|
||||
@ -10,6 +10,8 @@ import time
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('cpu', choices=[x.name.lower() for x in Cpu])
|
||||
parser.add_argument('matrix_file')
|
||||
parser.add_argument('format', type=str,
|
||||
choices=[fmt.name.lower() for fmt in Format])
|
||||
parser.add_argument('base_iterations', type=int)
|
||||
parser.add_argument('min_time_s', type=int)
|
||||
parser.add_argument('baseline_time_s', type=int)
|
||||
@ -19,6 +21,7 @@ parser.add_argument('--power', action='store_true')
|
||||
parser.add_argument('-d', '--debug', action='store_true')
|
||||
args = parser.parse_args()
|
||||
args.cpu = Cpu[args.cpu.upper()]
|
||||
args.format = Format[args.format.upper()]
|
||||
|
||||
python = {
|
||||
Cpu.ALTRA: 'python3',
|
||||
@ -40,16 +43,16 @@ def program(cpu: Cpu, matrix_file: str, iterations: int) -> list:
|
||||
return [
|
||||
'apptainer', 'run', 'pytorch-altra.sif', '-c',
|
||||
'numactl --cpunodebind=0 --membind=0 '
|
||||
+ f'python3 spmv.py {matrix_file} {iterations}']
|
||||
+ f'python3 spmv.py {iterations} csr -m {matrix_file}']
|
||||
elif cpu == Cpu.EPYC_7313P:
|
||||
return [
|
||||
'apptainer', 'run', 'pytorch-epyc_7313p.sif',
|
||||
'python3', 'spmv.py', f'{matrix_file}', f'{iterations}']
|
||||
'python3', 'spmv.py', f'{iterations}', 'csr', '-m', f'{matrix_file}']
|
||||
elif cpu == Cpu.XEON_4216:
|
||||
return [
|
||||
'apptainer', 'run', 'pytorch-xeon_4216.sif',
|
||||
'numactl', '--cpunodebind=0', '--membind=0',
|
||||
'python3', 'spmv.py', f'{matrix_file}', f'{iterations}']
|
||||
'python3', 'spmv.py', f'{iterations}', 'csr', '-m', f'{matrix_file}']
|
||||
|
||||
def baseline_power(cpu: Cpu, baseline_time_s: int) -> list:
|
||||
power_process = subprocess.Popen(['./power.sh', str(baseline_time_s)],
|
||||
@ -88,7 +91,7 @@ iterations = args.base_iterations
|
||||
program_result = run_program(program(args.cpu, args.matrix_file, iterations))
|
||||
while program_result[0][Stat.TIME_S.name] < args.min_time_s:
|
||||
# Increase the number of iterations by difference between the current time taken and the desired time.
|
||||
iterations *= 1 / ((args.min_time_s - program_result[0][Stat.TIME_S.name]) / args.min_time_s)
|
||||
iterations *= 1 / (program_result[0][Stat.TIME_S.name] / args.min_time_s)
|
||||
# Add another 5% for safety.
|
||||
iterations += iterations * 0.05
|
||||
iterations = int(iterations)
|
||||
@ -157,6 +160,9 @@ if args.power:
|
||||
args.baseline_time_s)
|
||||
)
|
||||
baseline_wattage = baseline_joules / (args.baseline_time_s * 2)
|
||||
if args.debug:
|
||||
print(baseline_joules)
|
||||
print(baseline_wattage)
|
||||
|
||||
result[Stat.J_1KI.name] = (
|
||||
(result[Stat.J.name] / result[Stat.ITERATIONS.name]) * 1000
|
||||
|
@ -1,4 +1,4 @@
|
||||
from data_stat import Stat
|
||||
from data_stat import Stat, Format
|
||||
|
||||
import torch, scipy
|
||||
import numpy as np
|
||||
@ -8,18 +8,48 @@ import json
|
||||
import sys, os
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('matrix_file', help='the input matrix (.mtx) file')
|
||||
parser.add_argument('iterations', type=int, help='the number of iterations of multiplication to perform')
|
||||
parser.add_argument('format', type=str,
|
||||
choices=[fmt.name.lower() for fmt in Format],
|
||||
help='the sparse format to use')
|
||||
parser.add_argument('-m', '--matrix_file', help='the input matrix (.mtx) file')
|
||||
parser.add_argument('-ss', '--synthetic_size', type=int,
|
||||
help='the synthetic matrix parameters size (rows)')
|
||||
parser.add_argument('-sd', '--synthetic_density', type=float,
|
||||
help='the synthetic matrix density (%)')
|
||||
args = parser.parse_args()
|
||||
args.format = Format[args.format.upper()]
|
||||
|
||||
device = 'cpu'
|
||||
|
||||
if args.matrix_file is not None:
|
||||
matrix = scipy.io.mmread(args.matrix_file)
|
||||
matrix = torch.sparse_coo_tensor(
|
||||
np.vstack((matrix.row, matrix.col)),
|
||||
matrix.data, matrix.shape,
|
||||
device=device
|
||||
).to_sparse_csr().type(torch.float)
|
||||
device=device, dtype=torch.float32)
|
||||
elif args.synthetic_size is not None and args.synthetic_density is not None:
|
||||
nnz = int((args.synthetic_size ** 2) * (args.synthetic_density / 100))
|
||||
row_indices = torch.randint(0, args.synthetic_size, (nnz,))
|
||||
col_indices = torch.randint(0, args.synthetic_size, (nnz,))
|
||||
indices = torch.stack([row_indices, col_indices])
|
||||
values = torch.randn(nnz)
|
||||
|
||||
matrix = torch.sparse_coo_tensor(
|
||||
indices, values,
|
||||
size=(args.synthetic_size, args.synthetic_size),
|
||||
device=device, dtype=torch.float32)
|
||||
else:
|
||||
print("No matrix specified!")
|
||||
exit(1)
|
||||
|
||||
if args.format == Format.CSR:
|
||||
matrix = matrix.to_sparse_csr().type(torch.float32)
|
||||
elif args.format == Format.COO:
|
||||
pass
|
||||
else:
|
||||
print("Unrecognized format!")
|
||||
exit(1)
|
||||
|
||||
vector = torch.rand(matrix.shape[1], device=device)
|
||||
|
||||
@ -35,7 +65,10 @@ end = time.time()
|
||||
|
||||
result = dict()
|
||||
|
||||
if args.matrix_file is not None:
|
||||
result[Stat.MATRIX_FILE.name] = os.path.splitext(os.path.basename(args.matrix_file))[0]
|
||||
else:
|
||||
result[Stat.MATRIX_FILE.name] = "synthetic"
|
||||
print(f"Matrix: {result[Stat.MATRIX_FILE.name]}", file=sys.stderr)
|
||||
|
||||
result[Stat.MATRIX_SHAPE.name] = matrix.shape
|
||||
|
Loading…
Reference in New Issue
Block a user