privateboss's picture
Upload 14 files
323c6ec verified
Raw
History Blame Contribute Delete
5.92 kB
import os
os.environ["TF_USE_LEGACY_KERAS"] = "1"
import psutil
import numpy as np
import tensorflow as tf
from tf_agents.environments import py_environment
from tf_agents.specs import array_spec
from tf_agents.trajectories import time_step as ts
from config import Config
try:
import pynvml
pynvml.nvmlInit()
HAS_NVML = True
except ImportError:
HAS_NVML = False
def configure_gpu():
"""Configures TensorFlow memory growth to prevent VRAM allocation errors."""
gpus = tf.config.list_physical_devices('GPU')
if gpus:
try:
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
print(f"✅ Found and configured {len(gpus)} GPU(s).")
except RuntimeError as e:
print(e)
else:
print("⚠️ No GPU found. Falling back to CPU.")
def get_system_telemetry():
"""Fetches real-time RAM, CPU, and GPU usage metrics for TensorBoard profiling."""
metrics = {
'system/ram_percent': psutil.virtual_memory().percent,
'system/cpu_percent': psutil.cpu_percent(),
}
if HAS_NVML:
try:
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
util = pynvml.nvmlDeviceGetUtilizationRates(handle)
temp = pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU)
mem = pynvml.nvmlDeviceGetMemoryInfo(handle)
metrics['hardware/gpu_utilization'] = float(util.gpu)
metrics['hardware/gpu_temperature_c'] = float(temp)
metrics['hardware/gpu_memory_percent'] = (mem.used / mem.total) * 100.0
except Exception:
pass
return metrics
class PettingZooToTFAgentsWrapper(py_environment.PyEnvironment):
"""Wraps a PettingZoo Parallel environment into a TF-Agents PyEnvironment."""
def __init__(self, pz_env):
super().__init__()
self._env = pz_env
self._current_info = {}
# Read host array shape sizes straight out of Config
total_nodes = Config.TOTAL_HOSTS()
# Red Actions: total_nodes * 4 choices | Blue Actions: total_nodes * 2 choices
self._action_spec = {
'red': array_spec.BoundedArraySpec(shape=(), dtype=np.int32, minimum=0, maximum=(total_nodes * 4) - 1, name='red_action'),
'blue': array_spec.BoundedArraySpec(shape=(), dtype=np.int32, minimum=0, maximum=(total_nodes * 2) - 1, name='blue_action')
}
# Match the complex dictionary nested schema
self._observation_spec = {
agent: {
'node_features': array_spec.BoundedArraySpec(shape=(total_nodes, 2), dtype=np.float32, minimum=0, maximum=1, name='features'),
'adjacency_matrix': array_spec.BoundedArraySpec(shape=(total_nodes, total_nodes), dtype=np.float32, minimum=0, maximum=1, name='topology')
} for agent in ['red', 'blue']
}
def action_spec(self):
return self._action_spec
def observation_spec(self):
return self._observation_spec
def reward_spec(self):
"""Declares multi-agent reward specs to prevent unpacking errors."""
return {
'red': array_spec.ArraySpec(shape=(), dtype=np.float32, name='red_reward'),
'blue': array_spec.ArraySpec(shape=(), dtype=np.float32, name='blue_reward')
}
def get_current_info(self):
"""Safely forwards custom internal metadata down to the trainer."""
return self._current_info
def _reset(self):
obs, infos = self._env.reset()
self._current_info = infos
# Guarantee observations map explicitly to nested dictionary signatures
formatted_obs = {
'red': {
'node_features': np.array(obs['red']['node_features'], dtype=np.float32),
'adjacency_matrix': np.array(obs['red']['adjacency_matrix'], dtype=np.float32)
},
'blue': {
'node_features': np.array(obs['blue']['node_features'], dtype=np.float32),
'adjacency_matrix': np.array(obs['blue']['adjacency_matrix'], dtype=np.float32)
}
}
initial_rewards = {
'red': np.array(0.0, dtype=np.float32),
'blue': np.array(0.0, dtype=np.float32)
}
return ts.TimeStep(
step_type=np.array(ts.StepType.FIRST, dtype=np.int32),
reward=initial_rewards,
discount=np.array(1.0, dtype=np.float32),
observation=formatted_obs
)
def _step(self, action):
# Convert actions into string keys for env.py mapping compliance
pz_actions = {'red': int(action['red']), 'blue': int(action['blue'])}
obs, rewards, terminations, truncations, infos = self._env.step(pz_actions)
self._current_info = infos
# Re-enforce nested array typing explicitly on step updates
formatted_obs = {
'red': {
'node_features': np.array(obs['red']['node_features'], dtype=np.float32),
'adjacency_matrix': np.array(obs['red']['adjacency_matrix'], dtype=np.float32)
},
'blue': {
'node_features': np.array(obs['blue']['node_features'], dtype=np.float32),
'adjacency_matrix': np.array(obs['blue']['adjacency_matrix'], dtype=np.float32)
}
}
formatted_rewards = {
'red': np.array(rewards['red'], dtype=np.float32),
'blue': np.array(rewards['blue'], dtype=np.float32)
}
if terminations['red'] or truncations['red']:
return ts.termination(formatted_obs, reward=formatted_rewards)
return ts.transition(formatted_obs, reward=formatted_rewards, discount=np.array(0.99, dtype=np.float32))