summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kobert <dennis@kobert.dev>2025-03-25 15:51:51 +0100
committerDennis Kobert <dennis@kobert.dev>2025-03-25 15:52:04 +0100
commita7da9c7140181ab4ef4af5e5f3222ca44741d66a (patch)
treebaf07ce81cf60ff43749dfa5eedfeb6ffe540b70
parent7f49625ee1cfadaf523da9e2c247fded90d82665 (diff)
Update ml script
-rw-r--r--power_predictor.py38
-rw-r--r--src/benchmark.rs49
2 files changed, 67 insertions, 20 deletions
diff --git a/power_predictor.py b/power_predictor.py
index 49e49fe..ca38498 100644
--- a/power_predictor.py
+++ b/power_predictor.py
@@ -14,6 +14,7 @@ import matplotlib.pyplot as plt
def load_data(csv_path):
# Read the CSV file
df = pd.read_csv(csv_path)
+ df = df.sample(frac=1).reset_index(drop=True)
# Extract target (power usage)
y = df['package_power_j'].values
@@ -82,8 +83,18 @@ class PowerEstimator(nn.Module):
def __init__(self, input_size):
super(PowerEstimator, self).__init__()
self.model = nn.Sequential(
+ # nn.Linear(input_size, 128),
+ # nn.ReLU(),
+ # nn.Dropout(0.3),
+ # nn.Linear(128, 64),
+ # nn.ReLU(),
+ # nn.Dropout(0.2),
+ # nn.Linear(64, 32),
+ # nn.ReLU(),
+ # nn.Linear(32, 1)
nn.Linear(input_size, 64),
nn.ReLU(),
+ # // leaky relu
nn.Dropout(0.2),
nn.Linear(64, 32),
nn.ReLU(),
@@ -94,10 +105,12 @@ class PowerEstimator(nn.Module):
return self.model(x)
# Step 5: Train the model
-def train_model(X, y, batch_size=32, epochs=100, lr=0.001):
+def train_model(X, y, batch_size=32, epochs=100, lr=0.001, early_stopping_patience=10):
# Split data into training and validation sets
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
+
+
# Scale the features
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
@@ -123,6 +136,9 @@ def train_model(X, y, batch_size=32, epochs=100, lr=0.001):
# Training loop
train_losses = []
val_losses = []
+ best_val_loss = float('inf')
+ epochs_without_improvement = 0
+ best_model_state = None
for epoch in range(epochs):
# Training
@@ -150,10 +166,27 @@ def train_model(X, y, batch_size=32, epochs=100, lr=0.001):
val_loss /= len(val_loader.dataset)
val_losses.append(val_loss)
+
+ # Early stopping check
+ if val_loss < best_val_loss:
+ best_val_loss = val_loss
+ best_model_state = model.state_dict().copy()
+ epochs_without_improvement = 0
+ else:
+ epochs_without_improvement += 1
# Print progress
if (epoch + 1) % 10 == 0:
print(f"Epoch {epoch+1}/{epochs}, Train Loss: {train_loss:.6f}, Val Loss: {val_loss:.6f}")
+
+ # Check early stopping
+ if epochs_without_improvement >= early_stopping_patience:
+ print(f"\nEarly stopping triggered after {epoch+1} epochs")
+ break
+
+ # Load best model
+ if best_model_state is not None:
+ model.load_state_dict(best_model_state)
# Plot training history
plt.figure(figsize=(10, 5))
@@ -233,11 +266,12 @@ def main():
print("Loading data...")
X, y = load_data(csv_path)
- X, y = remove_outliers(X, y)
# Impute missing values
print("\nImputing missing values...")
X_imputed = impute_missing_values(X)
+
+ X_imputed, y = remove_outliers(X_imputed, y)
# Analyze feature importance
print("\nAnalyzing feature importance...")
diff --git a/src/benchmark.rs b/src/benchmark.rs
index 6368fa8..6487c7a 100644
--- a/src/benchmark.rs
+++ b/src/benchmark.rs
@@ -379,15 +379,15 @@ fn define_available_events() -> Vec<(String, Event)> {
"cpu_cycles".to_string(),
Event::Hardware(Hardware::CPU_CYCLES),
),
- // (
- // "instructions".to_string(),
- // Event::Hardware(Hardware::INSTRUCTIONS),
- // ),
(
- "cache_references".to_string(),
- Event::Hardware(Hardware::CACHE_REFERENCES),
+ "instructions".to_string(),
+ Event::Hardware(Hardware::INSTRUCTIONS),
),
// (
+ // "cache_references".to_string(),
+ // Event::Hardware(Hardware::CACHE_REFERENCES),
+ // ),
+ // (
// "cache_misses".to_string(),
// Event::Hardware(Hardware::CACHE_MISSES),
// ),
@@ -395,14 +395,18 @@ fn define_available_events() -> Vec<(String, Event)> {
// "branch_instructions".to_string(),
// Event::Hardware(Hardware::BRANCH_INSTRUCTIONS),
// ),
- (
- "branch_misses".to_string(),
- Event::Hardware(Hardware::BRANCH_MISSES),
- ),
+ // (
+ // "branch_misses".to_string(),
+ // Event::Hardware(Hardware::BRANCH_MISSES),
+ // ),
(
"ref_cpu_cycles".to_string(),
Event::Hardware(Hardware::REF_CPU_CYCLES),
),
+ (
+ "stalled-cycles-frontend".to_string(),
+ Event::Hardware(Hardware::STALLED_CYCLES_FRONTEND),
+ ),
]);
// L1 Data Cache events
@@ -415,16 +419,25 @@ fn define_available_events() -> Vec<(String, Event)> {
// result: CacheResult::ACCESS,
// }),
// ),
- (
- "l1d_read_miss".to_string(),
- Event::Cache(Cache {
- which: WhichCache::L1D,
- operation: CacheOp::READ,
- result: CacheResult::MISS,
- }),
- ),
+ // (
+ // "l1d_read_miss".to_string(),
+ // Event::Cache(Cache {
+ // which: WhichCache::L1D,
+ // operation: CacheOp::READ,
+ // result: CacheResult::MISS,
+ // }),
+ // ),
]);
+ // events.push((
+ // "fp_ops_retired_by_type.all".to_string(),
+ // Event::Raw(4, 0xFF0A), // EventCode 0x0A with UMask 0xFF
+ // ));
+ events.push((
+ "sse_avx_ops_retired.all".to_string(),
+ Event::Raw(4, 0xFF0B), // EventCode 0x0B with UMask 0xFF
+ ));
+
// L1 Instruction Cache events
events.extend([
// (