-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimulate_packing.py
More file actions
91 lines (74 loc) · 4.08 KB
/
Copy pathsimulate_packing.py
File metadata and controls
91 lines (74 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
print("Loading machine usage sample...")
df_usage = pd.read_csv('Paper_Workspace/resources/machine_usage_sample_clean.csv')
# Convert timestamp to hour of the day
df_usage['hour'] = (df_usage['time_stamp'] // 3600) % 24
# Group by hour to get average utilizations
hourly = df_usage.groupby('hour')[['cpu_util_percent', 'mem_util_percent']].mean().reset_index()
TOTAL_SERVERS = 4000
TARGET_MEM_UTIL = 95.0
TARGET_CPU_UTIL = 80.0
# Scenario 1: Baseline (All servers on)
hourly['servers_baseline'] = TOTAL_SERVERS
# Scenario 2: Traditional Packing (Limited by Memory)
# We can only pack until memory hits 95%.
hourly['servers_trad_packing'] = TOTAL_SERVERS * (hourly['mem_util_percent'] / TARGET_MEM_UTIL)
# Scenario 3: CXL Memory Disaggregation (CPU and Memory decoupled)
# We can pack CPUs up to 80% regardless of local memory limits.
hourly['servers_cxl_disagg'] = TOTAL_SERVERS * (hourly['cpu_util_percent'] / TARGET_CPU_UTIL)
# Plotting the Server Requirements
plt.figure(figsize=(10, 5))
plt.plot(hourly['hour'], hourly['servers_baseline'], label='Baseline (No Packing)', linestyle='--', color='gray', linewidth=2)
plt.plot(hourly['hour'], hourly['servers_trad_packing'], label='Traditional Packing (Mem Bottleneck)', color='darkorange', marker='s')
plt.plot(hourly['hour'], hourly['servers_cxl_disagg'], label='CXL Disaggregation (CPU-focused Packing)', color='forestgreen', marker='o')
plt.title('Simulation: Required Active Servers under Different Architectures')
plt.xlabel('Hour of the Day (0-23)')
plt.ylabel('Number of Active Servers')
plt.ylim(0, 4500)
plt.xticks(range(24))
plt.legend()
plt.tight_layout()
plt.savefig('Paper_Workspace/resources/figure10_simulation_servers.png', dpi=150)
print("Saved figure10_simulation_servers.png")
# Calculate Energy and Carbon Savings (8 Days)
# Power Model: P(U) = 150 + 300*U
# Total Energy = Sum over 24 hours * 8 days
def calc_energy_mwh(servers_series, avg_cpu_series, days=8):
# If we pack workloads, the active servers run at the TARGET_CPU_UTIL (or baseline CPU).
# Wait, the total workload (total CPU units) remains the same.
# Total CPU workload = servers_series * active_cpu_util
# For baseline, active_cpu_util = avg_cpu_series
# For Traditional Packing, total workload / servers_trad_packing = active_cpu_util
total_cpu_workload = TOTAL_SERVERS * avg_cpu_series # per hour
# Active CPU util = total workload / active servers
active_cpu_util = total_cpu_workload / servers_series
# Cap at 100
active_cpu_util = active_cpu_util.clip(upper=100.0)
# Power = P_idle + 300 * (util / 100)
# Apply Power Usage Effectiveness (PUE) of 1.2 for cooling overhead
PUE = 1.2
hourly_power_kw = servers_series * (150.0 + 300.0 * (active_cpu_util / 100.0)) / 1000.0
total_mwh = hourly_power_kw.sum() * days * PUE # sum of 24 hours * 8 days * PUE
return total_mwh
e_baseline = calc_energy_mwh(hourly['servers_baseline'], hourly['cpu_util_percent'])
e_trad = calc_energy_mwh(hourly['servers_trad_packing'], hourly['cpu_util_percent'])
e_cxl = calc_energy_mwh(hourly['servers_cxl_disagg'], hourly['cpu_util_percent'])
print(f"Energy Baseline: {e_baseline:.2f} MWh")
print(f"Energy Trad: {e_trad:.2f} MWh")
print(f"Energy CXL: {e_cxl:.2f} MWh")
# Carbon Plot (Using Global Average 0.475 kg/kWh = 0.475 tons/MWh)
CARBON_INTENSITY = 0.475
carbon_data = pd.DataFrame({
'Architecture': ['Baseline', 'Traditional Packing', 'CXL Disaggregation'],
'Carbon (Tons CO2)': [e_baseline * CARBON_INTENSITY, e_trad * CARBON_INTENSITY, e_cxl * CARBON_INTENSITY]
})
plt.figure(figsize=(8, 5))
sns.barplot(data=carbon_data, x='Architecture', y='Carbon (Tons CO2)', palette='viridis')
plt.title('Simulated Carbon Footprint (8 Days)')
for p in plt.gca().patches:
plt.gca().annotate(f'{p.get_height():,.0f} Tons', (p.get_x() + p.get_width() / 2., p.get_height()), ha='center', va='center', xytext=(0, 5), textcoords='offset points')
plt.tight_layout()
plt.savefig('Paper_Workspace/resources/figure11_simulation_carbon.png', dpi=150)
print("Saved figure11_simulation_carbon.png")