kernel-env / kernel_env /server /rubrics.py
Shreyansh327's picture
Publish OpenEnv kernel environment and bounded GRPO proof artifacts
e313085 verified
Raw History Blame Contribute Delete
2.36 kB
"""Reward: correctness gate, then a speed score chosen by KERNEL_ENV_REWARD.
speedup (default): 0.3 + clamp(log2(t_ref / t_new), -0.2, 3.0). Correct-but-slower still earns >= 0.1;
log scale keeps rare 100x outliers from dominating group-normalized advantages (GRPO).
roofline: 0.3 + 2.7 * min(t_min / t_new, 1), the share of the hardware roof reached. Comparable across
memory-bound tasks (where ~1x vs PyTorch is already near optimal) and compute-bound ones. Falls back
to the speedup score when the roofline is unknown (GPU not in the peak table).
partial credit (KERNEL_ENV_PARTIAL_CREDIT=1): incorrect submissions that compiled earn a little, so
all-fail GRPO groups still have reward differences: 0.02 if it crashed or timed out at runtime, 0.05
if it ran but gave wrong output. Correct kernels always earn >= 0.1, so this never outranks them.
"""
import math
import os
from openenv.core.rubrics import Gate, Rubric, Sequential
class Correct(Rubric):
def forward(self, action, observation) -> float:
return 1.0 if observation.correct else 0.0
class Speedup(Rubric):
def forward(self, action, observation) -> float:
s = observation.speedup or 0.0
return 0.3 + min(max(math.log2(s), -0.2), 3.0) if s > 0 else 0.0
class Roofline(Rubric):
def __init__(self):
super().__init__()
self.fallback = Speedup()
def forward(self, action, observation) -> float:
f = observation.roofline_frac
return 0.3 + 2.7 * min(f, 1.0) if f else self.fallback(action, observation)
PARTIAL_CREDIT = {"runtime": 0.02, "timeout": 0.02, "correctness": 0.05}
class KernelReward(Rubric):
def __init__(self, speed: Rubric, partial: bool):
super().__init__()
self.speed = speed
self.partial = partial
def forward(self, action, observation) -> float:
if observation.correct:
return self.speed(action, observation)
return PARTIAL_CREDIT.get(observation.stage, 0.0) if self.partial else 0.0
def kernel_rubric(mode: str = "", partial: bool = None) -> Rubric:
mode = mode or os.environ.get("KERNEL_ENV_REWARD", "speedup")
if partial is None:
partial = os.environ.get("KERNEL_ENV_PARTIAL_CREDIT") == "1"
return KernelReward(Sequential(Gate(Correct()), {"speedup": Speedup, "roofline": Roofline}[mode]()), partial)