|
| 1 | +import os |
| 2 | +import time |
| 3 | +import subprocess |
| 4 | +from pathlib import Path |
| 5 | +import numpy as np |
| 6 | +import pandas as pd |
| 7 | +import plotly.graph_objects as go |
| 8 | +from plotly.subplots import make_subplots |
| 9 | + |
| 10 | +# =============================== |
| 11 | +# config |
| 12 | +# =============================== |
| 13 | + |
| 14 | +args = {} |
| 15 | +args['seed'] = 1234 |
| 16 | +args['main'] = Path(__file__) |
| 17 | +args['cwd'] = args['main'].parent.parent |
| 18 | +args['src'] = args['cwd'] / 'src' |
| 19 | +args['hpp'] = args['src'] / 'headers.hpp' |
| 20 | +args['cmdstan'] = Path(os.path.expanduser("~")) / '.cmdstan' / 'cmdstan-2.35.0' |
| 21 | +args['stanc_args'] = {"include-paths": [str(args['src'])]} |
| 22 | +args['cpp_options'] = {"LDFLAGS": f"{str(args['src'])}/bnb/bnb_lpmf.o -L{os.environ['CUDA_HOME']}/lib64 -lcudart"} |
| 23 | +args['stan_dir'] = args['cwd'] / 'model' |
| 24 | + |
| 25 | +import sys |
| 26 | +sys.path.append(str(args['cwd'])) |
| 27 | +from utils import stan_model, beta_neg_binomial_rng |
| 28 | + |
| 29 | + |
| 30 | +# =============================== |
| 31 | +# execution |
| 32 | +# =============================== |
| 33 | + |
| 34 | +command = ["nvcc", "-O3", "-lineinfo", "-c", str(args['src'])+"/bnb/bnb_lpmf.cu", "-o", str(args['src'])+"/bnb/bnb_lpmf.o"] |
| 35 | +result = subprocess.run(command, capture_output=True, text=True) |
| 36 | +print("stdout:", result.stdout) |
| 37 | +print("stderr:", result.stderr) |
| 38 | + |
| 39 | +data_sizes = [4000, 6000, 8000, 10000, 12000, 14000, 18000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000, 120000, 130000, 140000, 150000] |
| 40 | +results = [] |
| 41 | + |
| 42 | +def run_and_measure_time(model, data_size): |
| 43 | + data = beta_neg_binomial_rng(r=6, alpha=4, beta=0.5, y_max=500, size=data_size, seed=args['seed']) |
| 44 | + stan_data = { |
| 45 | + 'N': len(data), |
| 46 | + 'y': data, |
| 47 | + } |
| 48 | + start_time = time.time() |
| 49 | + model.sample(stan_data, |
| 50 | + **{"chains": 4, "iter_warmup": 500, "iter_sampling": 500, |
| 51 | + "show_console": False, "seed": args['seed'], "refresh": 20}) |
| 52 | + elapsed_time = time.time() - start_time |
| 53 | + return elapsed_time |
| 54 | + |
| 55 | +cpu_model = stan_model(args['stan_dir'] / 'model_bnb.stan') |
| 56 | +cpu_model.compile(user_header=args['hpp'], |
| 57 | + stanc_options=args['stanc_args']) |
| 58 | +gpu_model = stan_model(args['stan_dir'] / 'model_cu_bnb.stan') |
| 59 | +gpu_model.compile(user_header=args['hpp'], |
| 60 | + stanc_options=args['stanc_args'], |
| 61 | + cpp_options=args['cpp_options']) |
| 62 | + |
| 63 | +for size in data_sizes: |
| 64 | + # Test CPU version |
| 65 | + cpu_time = run_and_measure_time(cpu_model, size) |
| 66 | + results.append({'Data Size': size, 'Model Type': 'CPU', 'Time (seconds)': cpu_time}) |
| 67 | + # Test GPU version |
| 68 | + gpu_time = run_and_measure_time(gpu_model, size) |
| 69 | + results.append({'Data Size': size, 'Model Type': 'GPU', 'Time (seconds)': gpu_time}) |
| 70 | + |
| 71 | +df = pd.DataFrame(results) |
| 72 | +df.to_csv(args['cwd'] / 'output' / 'model_performance.csv', index=False) |
| 73 | + |
| 74 | + |
| 75 | + |
| 76 | +# =============================== |
| 77 | +# comparison |
| 78 | +# =============================== |
| 79 | + |
| 80 | +df_cpu = df[df['Model Type'] == 'CPU'].set_index('Data Size') |
| 81 | +df_gpu = df[df['Model Type'] == 'GPU'].set_index('Data Size') |
| 82 | +df_ratio = (df_cpu['Time (seconds)'] / df_gpu['Time (seconds)']).reset_index() |
| 83 | +df_ratio.columns = ['Data Size', 'CPU/GPU Ratio'] |
| 84 | + |
| 85 | +fig = make_subplots(rows=1, cols=2, |
| 86 | + horizontal_spacing=0.05, |
| 87 | + vertical_spacing=0.03, |
| 88 | + subplot_titles=('Time (seconds)', 'CPU/GPU Time Ratio') |
| 89 | + ) |
| 90 | + |
| 91 | +fig.add_trace( |
| 92 | + go.Scatter(x=df[df['Model Type'] == 'CPU']['Data Size'], y=df[df['Model Type'] == 'CPU']['Time (seconds)'], mode='lines', name='CPU'), |
| 93 | + row=1, col=1 |
| 94 | +) |
| 95 | +fig.add_trace( |
| 96 | + go.Scatter(x=df[df['Model Type'] == 'CPU']['Data Size'], y=df[df['Model Type'] == 'GPU']['Time (seconds)'], mode='lines', name='GPU'), |
| 97 | + row=1, col=1 |
| 98 | +) |
| 99 | + |
| 100 | +fig.add_trace( |
| 101 | + go.Scatter(x=df_ratio['Data Size'], y=df_ratio['CPU/GPU Ratio'], mode='lines', name='CPU/GPU'), |
| 102 | + row=1, col=2 |
| 103 | +) |
| 104 | + |
| 105 | +# fig.update_yaxes(title_text='Time (seconds)', row=1, col=1) |
| 106 | +# fig.update_yaxes(title_text='CPU/GPU Ratio', row=1, col=2) |
| 107 | +fig.update_xaxes(title_text='Data Size', row=1, col=1) |
| 108 | +fig.update_xaxes(title_text='Data Size', row=1, col=2) |
| 109 | + |
| 110 | +fig.update_yaxes(zeroline=False,) |
| 111 | +fig.update_xaxes(dtick="20000") |
| 112 | +fig.update_layout(title_text='', |
| 113 | + showlegend=True, |
| 114 | + height=500, |
| 115 | + width=1200) |
| 116 | +fig.write_image(args['cwd'] / 'output' / 'model_performance.pdf') |
| 117 | + |
| 118 | + |
| 119 | + |
0 commit comments