Compare commits

..

2 Commits

Author SHA1 Message Date
firestar5683 08b519ca77 files 2026-09-02 11:17:46 -05:00
firestar5683 449cb11938 Pin 2026-09-02 09:59:09 -05:00
369 changed files with 14725 additions and 7582 deletions
+19 -5
View File
@@ -159,7 +159,21 @@ All four files must be updated together.
## Manifest ## Manifest
Generate the base manifest after compilation, then namespace the release artifacts as v23: The current test branch uses manifest v25 and requests v25 only. Seed the new
manifest from the previous catalog, then replace entries as artifacts are
rebuilt with the pinned runtime:
```bash
cp /path/to/model_names_v24.json /path/to/model_names_v25.json
```
The current tinygrad pin is `f6fc4e3f2c3db5fae1e19cbfbc3ad9fc579a12ae`, from
`openpilot` `origin/master` (`bump tg + TC_MIN_GLOBALS`). StarPilot's
multi-model `modeld` remains in place; do not replace it with upstream's
single-model `modeld`.
For the older namespace migration workflow, generate the base manifest after
compilation and namespace the release artifacts as v23:
```bash ```bash
python3 scripts/model_rebuild_pipeline.py manifest \ python3 scripts/model_rebuild_pipeline.py manifest \
@@ -175,9 +189,9 @@ python3 scripts/namespace_model_artifacts.py \
The namespace command changes IDs such as `tr1422` to `tr14223`, renames the The namespace command changes IDs such as `tr1422` to `tr14223`, renames the
compiled and upload-ready files, and writes an ID map. It preserves display compiled and upload-ready files, and writes an ID map. It preserves display
names and behavioral versions. The current model manager requests v23 only; names and behavioral versions. The current model manager requests v25 only; the
the manifest is fetched from `Models/model_names_v23.json`, while v22 remains manifest is fetched from `Models/model_names_v25.json`. Devices still running
available for devices that have not updated yet. the prior branch continue to request their existing manifest version.
After importing newly compiled sources, normalize the release namespace before After importing newly compiled sources, normalize the release namespace before
copying files into either resource repository: copying files into either resource repository:
@@ -205,4 +219,4 @@ Compilation validates JIT capture/replay, pickle round-trip, finite outputs, met
4. Confirm `driverStateV2` on both supported camera resolutions. 4. Confirm `driverStateV2` on both supported camera resolutions.
5. Test download, selection, deletion, randomization, migration, and fallback in both device UIs and Galaxy. 5. Test download, selection, deletion, randomization, migration, and fallback in both device UIs and Galaxy.
The built-in RDF artifact is `selfdrive/modeld/models/driving_tinygrad.pkl`. If migration cannot download the selected v23 artifact, StarPilot switches to that built-in model. The built-in RDF artifact is `selfdrive/modeld/models/driving_tinygrad.pkl`. If migration cannot download the selected v25 artifact, StarPilot switches to that built-in model.
+1 -1
View File
@@ -21,7 +21,7 @@ fi
export QCOM_PRIORITY=12 export QCOM_PRIORITY=12
if [ -z "$AGNOS_VERSION" ]; then if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="19.6.17" export AGNOS_VERSION="19.6.16"
fi fi
if [ -z "$AGNOS_ACCEPTED_VERSIONS" ]; then if [ -z "$AGNOS_ACCEPTED_VERSIONS" ]; then
@@ -8,9 +8,9 @@ from opendbc.car.lateral import apply_driver_steer_torque_limits, apply_steer_an
from opendbc.car.common.conversions import Conversions as CV from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.hyundai import hyundaicanfd, hyundaican from opendbc.car.hyundai import hyundaicanfd, hyundaican
from opendbc.car.hyundai.hyundaicanfd import CanBus from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, Buttons, CarControllerParams, CAR, CANFD_ANGLE_LONGITUDINAL_CAR, \ from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR, CANFD_ANGLE_LONGITUDINAL_CAR, \
CANFD_RADAR_LIVE_LONGITUDINAL_CAR, CANFD_ALT_BUTTONS_RESUME_CAR, kia_ev6_gt_line_longitudinal_tuning, \ CANFD_RADAR_LIVE_LONGITUDINAL_CAR, CANFD_ALT_BUTTONS_RESUME_CAR, kia_ev6_gt_line_longitudinal_tuning, \
KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID, CANFD_DAW_SUPPRESSION_CAR KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID
from opendbc.car.interfaces import CarControllerBase from opendbc.car.interfaces import CarControllerBase
from opendbc.car.vehicle_model import VehicleModel from opendbc.car.vehicle_model import VehicleModel
from openpilot.common.params import Params from openpilot.common.params import Params
@@ -777,8 +777,6 @@ class CarController(CarControllerBase):
left_lane_warning, right_lane_warning, lka_icon)) left_lane_warning, right_lane_warning, lka_icon))
if self.CP.carFingerprint == CAR.KIA_RAY_EV: if self.CP.carFingerprint == CAR.KIA_RAY_EV:
self._ray_lkas11_active = True self._ray_lkas11_active = True
if getattr(self.FPCP, "flags", 0) & HyundaiStarPilotFlags.HAS_LKAS12:
can_sends.append(hyundaican.create_lkas12(self.packer, CS.lkas12))
# Button messages # Button messages
if not self.long_active_ecu: if not self.long_active_ecu:
@@ -852,6 +850,9 @@ class CarController(CarControllerBase):
) )
# steering control # steering control
# The first-generation Electrified GV70 expects the synthesized LKAS status
# payload. Forwarding its stock status bits leaves lane-safety state asserted
# while StarPilot is suppressing the stock LFA path.
preserve_stock_lkas = bool(self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING) and \ preserve_stock_lkas = bool(self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING) and \
not self.long_active_ecu and self.CP.carFingerprint != CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN and \ not self.long_active_ecu and self.CP.carFingerprint != CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN and \
preserve_stock_canfd_lkas_status(self.CP.carFingerprint) preserve_stock_canfd_lkas_status(self.CP.carFingerprint)
@@ -894,9 +895,6 @@ class CarController(CarControllerBase):
can_sends.extend(hyundaicanfd.create_inactive_angle_steering_messages(self.packer, self.CAN, can_sends.extend(hyundaicanfd.create_inactive_angle_steering_messages(self.packer, self.CAN,
inactive_steering_angle)) inactive_steering_angle))
if self.CP.carFingerprint in CANFD_DAW_SUPPRESSION_CAR and getattr(CS, "stock_daw_msg", None):
can_sends.append(hyundaicanfd.create_suppress_daw(self.packer, self.CAN, CS.stock_daw_msg))
# prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU # prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU
suppress_lfa = bool(lka_steering) suppress_lfa = bool(lka_steering)
if angle_lkas_alt: if angle_lkas_alt:
+2 -9
View File
@@ -10,7 +10,6 @@ from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, HyundaiStarPilotSafetyFlags, CAR, DBC, Buttons, CarControllerParams, \ from opendbc.car.hyundai.values import HyundaiFlags, HyundaiStarPilotFlags, HyundaiStarPilotSafetyFlags, CAR, DBC, Buttons, CarControllerParams, \
CANFD_ANGLE_LONGITUDINAL_CAR, CANFD_CORNER_RADAR_BSM_CAR, \ CANFD_ANGLE_LONGITUDINAL_CAR, CANFD_CORNER_RADAR_BSM_CAR, \
CANFD_ALT_BUTTONS_RESUME_CAR, \ CANFD_ALT_BUTTONS_RESUME_CAR, \
CANFD_DAW_SUPPRESSION_CAR, \
hyundai_cancel_button_enables_cruise, ALT_BUS_LDA_BUTTON_CARS, ALT_BUS_LDA_BUTTON_SWL_STAT_CARS hyundai_cancel_button_enables_cruise, ALT_BUS_LDA_BUTTON_CARS, ALT_BUS_LDA_BUTTON_SWL_STAT_CARS
from opendbc.car.interfaces import CarStateBase from opendbc.car.interfaces import CarStateBase
@@ -143,8 +142,6 @@ class CarState(CarStateBase):
self.msg_364 = {} self.msg_364 = {}
self.lfa_block_msg = {} self.lfa_block_msg = {}
self.stock_lkas_msg = {} self.stock_lkas_msg = {}
self.lkas12 = {}
self.stock_daw_msg = {}
self.stock_lfa_msg = {} self.stock_lfa_msg = {}
self.stock_lfahda_cluster_msg = {} self.stock_lfahda_cluster_msg = {}
self.stock_camera_lead_visible = False self.stock_camera_lead_visible = False
@@ -443,8 +440,6 @@ class CarState(CarStateBase):
self.lkas11 = {} self.lkas11 = {}
else: else:
self.lkas11 = copy.copy(cp_cam.vl["LKAS11"]) self.lkas11 = copy.copy(cp_cam.vl["LKAS11"])
if getattr(self.FPCP, "flags", 0) & HyundaiStarPilotFlags.HAS_LKAS12:
self.lkas12 = copy.copy(cp_cam.vl["LKAS12"])
self.clu11 = copy.copy(cp.vl["CLU11"]) self.clu11 = copy.copy(cp.vl["CLU11"])
self.steer_state = cp.vl["MDPS12"]["CF_Mdps_ToiActive"] # 0 NOT ACTIVE, 1 ACTIVE self.steer_state = cp.vl["MDPS12"]["CF_Mdps_ToiActive"] # 0 NOT ACTIVE, 1 ACTIVE
if not self.main_cruise_tracking: if not self.main_cruise_tracking:
@@ -615,8 +610,6 @@ class CarState(CarStateBase):
if self.CP.carFingerprint in CANFD_ANGLE_LONGITUDINAL_CAR and cp.ts_nanos["FR_CMR_01_10ms"]["FR_CMR_Crc1Val"] > 0: if self.CP.carFingerprint in CANFD_ANGLE_LONGITUDINAL_CAR and cp.ts_nanos["FR_CMR_01_10ms"]["FR_CMR_Crc1Val"] > 0:
hba_icon = int(cp.vl["FR_CMR_01_10ms"]["HBA_IndLmpReq"]) hba_icon = int(cp.vl["FR_CMR_01_10ms"]["HBA_IndLmpReq"])
self.hba_icon = hba_icon if hba_icon in (1, 2) else 0 self.hba_icon = hba_icon if hba_icon in (1, 2) else 0
if self.CP.carFingerprint in CANFD_DAW_SUPPRESSION_CAR and cp.ts_nanos["FR_CMR_01_10ms"]["FR_CMR_Crc1Val"] > 0:
self.stock_daw_msg = copy.copy(cp.vl["FR_CMR_01_10ms"])
if cp.ts_nanos["BLINKER_STALKS"]["CHECKSUM_MAYBE"] > 0: if cp.ts_nanos["BLINKER_STALKS"]["CHECKSUM_MAYBE"] > 0:
self.stock_blinker_stalks_ts = cp.ts_nanos["BLINKER_STALKS"]["CHECKSUM_MAYBE"] self.stock_blinker_stalks_ts = cp.ts_nanos["BLINKER_STALKS"]["CHECKSUM_MAYBE"]
@@ -680,7 +673,7 @@ class CarState(CarStateBase):
] ]
if CP.enableBsm: if CP.enableBsm:
msgs.append(("BLINDSPOTS_REAR_CORNERS", 0)) msgs.append(("BLINDSPOTS_REAR_CORNERS", 0))
if CP.carFingerprint in CANFD_ANGLE_LONGITUDINAL_CAR | CANFD_DAW_SUPPRESSION_CAR: if CP.carFingerprint in CANFD_ANGLE_LONGITUDINAL_CAR:
msgs.append(("BLINDSPOTS_FRONT_CORNER_2", 0)) msgs.append(("BLINDSPOTS_FRONT_CORNER_2", 0))
msgs.append(("FR_CMR_01_10ms", 0)) msgs.append(("FR_CMR_01_10ms", 0))
if CP.flags & HyundaiFlags.EV: if CP.flags & HyundaiFlags.EV:
@@ -737,7 +730,7 @@ class CarState(CarStateBase):
parsers = { parsers = {
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, 0), Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, 0),
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS12", 0)], 2), Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2),
} }
if CP.carFingerprint in ALT_BUS_LDA_BUTTON_CARS: if CP.carFingerprint in ALT_BUS_LDA_BUTTON_CARS:
parsers[Bus.alt] = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CLU13", 0)], 1) parsers[Bus.alt] = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CLU13", 0)], 1)
@@ -81,10 +81,6 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
values["CF_Lkas_LdwsActivemode"] = 2 values["CF_Lkas_LdwsActivemode"] = 2
if CP.carFingerprint == CAR.KIA_RAY_EV: if CP.carFingerprint == CAR.KIA_RAY_EV:
if not enabled:
values["CF_Lkas_LdwsActivemode"] = lkas11["CF_Lkas_LdwsActivemode"]
values["CF_Lkas_LdwsSysState"] = lkas11["CF_Lkas_LdwsSysState"]
values["CF_Lkas_FcwOpt_USM"] = lkas11["CF_Lkas_FcwOpt_USM"]
values["CF_Lkas_LdwsOpt_USM"] = 0 values["CF_Lkas_LdwsOpt_USM"] = 0
values["CF_Lkas_Chksum"] = 0 values["CF_Lkas_Chksum"] = 0
@@ -106,19 +102,6 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
return packer.make_can_msg("LKAS11", 0, values) return packer.make_can_msg("LKAS11", 0, values)
def create_lkas12(packer, lkas12):
values = {s: lkas12[s] for s in (
"CF_Lkas_TsrSlifOpt",
"CF_LkasTsrStatus",
"CF_Lkas_TsrSpeed_Display_Clu",
"CF_LkasTsrSpeed_Display_Navi",
"CF_Lkas_TsrAddinfo_Display",
"CF_Lkas_Daw_USM",
) if s in lkas12}
values["CF_LkasDawStatus"] = 0
return packer.make_can_msg("LKAS12", 0, values)
def create_checksum_can_canfd_blended(packer, bus, addr, values): def create_checksum_can_canfd_blended(packer, bus, addr, values):
dat = packer.make_can_msg(addr, bus, values)[1] dat = packer.make_can_msg(addr, bus, values)[1]
return hyundai_checksum(dat[1:8]) return hyundai_checksum(dat[1:8])
@@ -63,6 +63,61 @@ def _update_checksum(packer, address: int, dat: bytearray) -> None:
_set_value(dat, sig_checksum, checksum) _set_value(dat, sig_checksum, checksum)
def _set_little_endian_bits(dat: bytearray, lsb: int, size: int, value: int) -> None:
"""Write the legacy HDA-II field layout without changing the generated DBC aliases."""
value &= (1 << size) - 1
bit = lsb
remaining = size
while remaining:
byte = bit // 8
shift = bit % 8
chunk_size = min(remaining, 8 - shift)
mask = ((1 << chunk_size) - 1) << shift
dat[byte] = (dat[byte] & ~mask) | ((value & ((1 << chunk_size) - 1)) << shift)
value >>= chunk_size
bit += chunk_size
remaining -= chunk_size
def _create_gv70_lka_status_msg(packer, CAN, message_name: str, bus: int, enabled: bool,
lat_active: bool, apply_torque: int):
values = {
"LKA_MODE": 2,
"LKA_ICON": 2 if enabled else 1,
"TORQUE_REQUEST": apply_torque,
"STEER_REQ": 1 if lat_active else 0,
"LKA_ASSIST": 0,
"STEER_MODE": 0,
"DAMP_FACTOR": 100,
}
address, raw, _ = packer.make_can_msg(message_name, bus, values)
dat = bytearray(raw)
legacy_fields = (
(24, 3, 2),
(27, 3, 0),
(30, 2, 0),
(32, 2, 0),
(34, 2, 0),
(36, 2, 0),
(38, 3, 2 if enabled else 1),
(52, 2, 1 if lat_active else 0),
(54, 2, 0),
(56, 1, 0),
(60, 4, 0),
(80, 2, 0),
)
for lsb, size, value in legacy_fields:
_set_little_endian_bits(dat, lsb, size, value)
_set_little_endian_bits(dat, 64 if message_name == "LKAS" else 104, 8, 100)
if message_name == "LKAS":
_set_little_endian_bits(dat, 84, 3, 0)
_update_checksum(packer, address, dat)
return address, bytes(dat), bus
def _create_angle_lfa_msg(packer, CAN, values, apply_angle: float, lat_active: bool, torque_reduction_gain: float): def _create_angle_lfa_msg(packer, CAN, values, apply_angle: float, lat_active: bool, torque_reduction_gain: float):
address = packer.dbc.name_to_msg["LFA"].address address = packer.dbc.name_to_msg["LFA"].address
dat = packer.pack(address, values) dat = packer.pack(address, values)
@@ -101,6 +156,13 @@ def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque,
if lka_icon is None: if lka_icon is None:
lka_icon = 2 if enabled else 1 lka_icon = 2 if enabled else 1
if CP.carFingerprint == CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN and CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
ret = []
if CP.openpilotLongitudinalControl:
ret.append(_create_gv70_lka_status_msg(packer, CAN, "LFA", CAN.ECAN, enabled, lat_active, apply_torque))
ret.append(_create_gv70_lka_status_msg(packer, CAN, "LKAS", CAN.ACAN, enabled, lat_active, apply_torque))
return ret
angle_lkas_alt = CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING and CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT angle_lkas_alt = CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING and CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT
control_values = { control_values = {
@@ -243,12 +305,6 @@ def create_suppress_lfa(packer, CAN, lfa_block_msg, lka_steering_alt):
return packer.make_can_msg(suppress_msg, CAN.ACAN, values) return packer.make_can_msg(suppress_msg, CAN.ACAN, values)
def create_suppress_daw(packer, CAN, daw_msg):
values = copy.copy(daw_msg)
values["DAW_WrnMsgSta"] = 0
return packer.make_can_msg("FR_CMR_01_10ms", CAN.ECAN, values)
def create_buttons(packer, CP, CAN, cnt, btn=0, base_values=None, left_paddle=False, right_paddle=False): def create_buttons(packer, CP, CAN, cnt, btn=0, base_values=None, left_paddle=False, right_paddle=False):
values = {k: v for k, v in base_values.items() if k not in ("CHECKSUM", "_CHECKSUM", "COUNTER")} if base_values else {} values = {k: v for k, v in base_values.items() if k not in ("CHECKSUM", "_CHECKSUM", "COUNTER")} if base_values else {}
values.update({ values.update({
@@ -570,41 +570,6 @@ class TestHyundaiFingerprint:
assert not (CP.flags & HyundaiFlags.CANFD_LKA_STEERING) assert not (CP.flags & HyundaiFlags.CANFD_LKA_STEERING)
assert bool(CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) assert bool(CP.flags & HyundaiFlags.CANFD_CAMERA_SCC)
def test_ioniq_6_filters_stock_driver_attention_warning(self):
CP = CarParams.new_message()
CP.carFingerprint = CAR.HYUNDAI_IONIQ_6
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_LKA_STEERING |
HyundaiFlags.CANFD_LKA_STEERING_ALT)
CP.openpilotLongitudinalControl = False
controller = CarController(DBC[CP.carFingerprint], CP)
controller.frame = 1
can_bus = CanBus(CP)
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("FR_CMR_01_10ms", 0)], can_bus.ECAN)
stock_daw_msg = {
"FR_CMR_AlvCnt1Val": 7,
"DAW_SysSta": 6,
"DAW_WrnMsgSta": 1,
"HBA_IndLmpReq": 2,
}
cc = SimpleNamespace(enabled=True, latActive=True,
actuators=SimpleNamespace(longControlState=LongCtrlState.off),
leftBlinker=False, rightBlinker=False, hudControl=SimpleNamespace())
cs = SimpleNamespace(stock_lfa_msg=None, stock_lkas_msg={}, lfa_block_msg={}, stock_daw_msg=stock_daw_msg,
out=SimpleNamespace(steeringAngleDeg=0.0, gearShifter=structs.CarState.GearShifter.drive))
msgs = controller.create_canfd_msgs(0, True, 0.0, 0.0, 0.0, 0.0, False, cc.hudControl, cs, cc,
get_test_toggles(), lka_icon=2, lfa_icon=2)
daw_msgs = [msg for msg in msgs if msg[0] == 0x11A]
assert len(daw_msgs) == 1
parser.update([(1, daw_msgs)])
assert parser.can_valid
assert parser.vl["FR_CMR_01_10ms"]["DAW_SysSta"] == 6
assert parser.vl["FR_CMR_01_10ms"]["DAW_WrnMsgSta"] == 0
assert parser.vl["FR_CMR_01_10ms"]["HBA_IndLmpReq"] == 2
def test_ioniq_6_clears_torque_with_inactive_safety_request(self): def test_ioniq_6_clears_torque_with_inactive_safety_request(self):
ioniq_6_cp = SimpleNamespace(carFingerprint=CAR.HYUNDAI_IONIQ_6) ioniq_6_cp = SimpleNamespace(carFingerprint=CAR.HYUNDAI_IONIQ_6)
other_cp = SimpleNamespace(carFingerprint=CAR.KIA_EV6) other_cp = SimpleNamespace(carFingerprint=CAR.KIA_EV6)
@@ -745,7 +710,7 @@ class TestHyundaiFingerprint:
assert parser.vl["LKAS11"]["CF_Lkas_LdwsActivemode"] == 0 assert parser.vl["LKAS11"]["CF_Lkas_LdwsActivemode"] == 0
assert parser.vl["LKAS11"]["CF_Lkas_FcwOpt_USM"] == 0 assert parser.vl["LKAS11"]["CF_Lkas_FcwOpt_USM"] == 0
def test_kia_ray_ev_preserves_stock_inactive_lkas_status(self): def test_kia_ray_ev_preserves_stock_lkas_option(self):
fingerprint = gen_empty_fingerprint() fingerprint = gen_empty_fingerprint()
fingerprint[2][0x485] = 4 fingerprint[2][0x485] = 4
CP = CarInterface.get_params(CAR.KIA_RAY_EV, fingerprint, [], False, False, False, None) CP = CarInterface.get_params(CAR.KIA_RAY_EV, fingerprint, [], False, False, False, None)
@@ -753,46 +718,15 @@ class TestHyundaiFingerprint:
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS11", 0)], 0) parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS11", 0)], 0)
lkas11 = parser.vl["LKAS11"]
lkas11.update({
"CF_Lkas_LdwsActivemode": 0,
"CF_Lkas_LdwsSysState": 1,
"CF_Lkas_FcwOpt_USM": 1,
})
msg = hyundaican.create_lkas11( msg = hyundaican.create_lkas11(
packer, 0, CP, 0, True, False, lkas11, False, 4, False, packer, 0, CP, 0, True, False, parser.vl["LKAS11"], False, 4, False,
True, True, 0, 0, 2,
)
parser.update([(1, [msg])])
assert parser.vl["LKAS11"]["CF_Lkas_LdwsActivemode"] == 0
assert parser.vl["LKAS11"]["CF_Lkas_LdwsSysState"] == 1
assert parser.vl["LKAS11"]["CF_Lkas_LdwsOpt_USM"] == 0
assert parser.vl["LKAS11"]["CF_Lkas_FcwOpt_USM"] == 1
def test_kia_ray_ev_uses_active_lkas_status_when_enabled(self):
fingerprint = gen_empty_fingerprint()
fingerprint[2][0x485] = 4
CP = CarInterface.get_params(CAR.KIA_RAY_EV, fingerprint, [], False, False, False, None)
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS11", 0)], 0)
lkas11 = parser.vl["LKAS11"]
lkas11.update({
"CF_Lkas_LdwsActivemode": 0,
"CF_Lkas_LdwsSysState": 1,
"CF_Lkas_FcwOpt_USM": 1,
})
msg = hyundaican.create_lkas11(
packer, 0, CP, 0, True, False, lkas11, False, 4, True,
True, True, 0, 0, 2, True, True, 0, 0, 2,
) )
parser.update([(1, [msg])]) parser.update([(1, [msg])])
assert parser.vl["LKAS11"]["CF_Lkas_LdwsActivemode"] == 3 assert parser.vl["LKAS11"]["CF_Lkas_LdwsActivemode"] == 3
assert parser.vl["LKAS11"]["CF_Lkas_LdwsSysState"] == 4
assert parser.vl["LKAS11"]["CF_Lkas_LdwsOpt_USM"] == 0 assert parser.vl["LKAS11"]["CF_Lkas_LdwsOpt_USM"] == 0
assert parser.vl["LKAS11"]["CF_Lkas_FcwOpt_USM"] == 2 assert parser.vl["LKAS11"]["CF_Lkas_FcwOpt_USM"] == 1
def test_kia_ray_ev_delays_first_lkas11(self): def test_kia_ray_ev_delays_first_lkas11(self):
fingerprint = gen_empty_fingerprint() fingerprint = gen_empty_fingerprint()
@@ -862,37 +796,6 @@ class TestHyundaiFingerprint:
palisade_2023 = CarInterface.get_params(CAR.HYUNDAI_PALISADE_2023, gen_empty_fingerprint(), [], True, False, False, None) palisade_2023 = CarInterface.get_params(CAR.HYUNDAI_PALISADE_2023, gen_empty_fingerprint(), [], True, False, False, None)
assert palisade_2023.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON assert palisade_2023.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON
def test_lkas12_da_warning_is_filtered_for_camera_fingerprint(self):
fingerprint = gen_empty_fingerprint()
fingerprint[2][0x53E] = 6
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA_HYBRID, fingerprint, [], False, False, False, None)
FPCP = CarInterface.get_starpilot_params(CAR.HYUNDAI_SONATA_HYBRID, fingerprint, [], CP, get_test_toggles())
assert FPCP.flags & HyundaiStarPilotFlags.HAS_LKAS12
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
stock = {
"CF_Lkas_TsrSlifOpt": 3,
"CF_LkasTsrStatus": 2,
"CF_Lkas_TsrSpeed_Display_Clu": 80,
"CF_LkasTsrSpeed_Display_Navi": 70,
"CF_Lkas_TsrAddinfo_Display": 1,
"CF_Lkas_Daw_USM": 0,
"CF_LkasDawStatus": 1,
}
msg = hyundaican.create_lkas12(packer, stock)
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS12", 0)], 0)
parser.update([(1, [msg])])
assert parser.can_valid
assert parser.vl["LKAS12"]["CF_LkasDawStatus"] == 0
assert parser.vl["LKAS12"]["CF_Lkas_TsrSpeed_Display_Clu"] == 80
no_lkas12 = CarInterface.get_params(CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], False, False, False, None)
no_lkas12_fpcp = CarInterface.get_starpilot_params(
CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], no_lkas12, get_test_toggles(),
)
assert not (no_lkas12_fpcp.flags & HyundaiStarPilotFlags.HAS_LKAS12)
def test_carnival_lka_button_does_not_enable_angle_steering_safety(self): def test_carnival_lka_button_does_not_enable_angle_steering_safety(self):
fingerprint = gen_empty_fingerprint() fingerprint = gen_empty_fingerprint()
fingerprint[0][0x391] = 8 fingerprint[0][0x391] = 8
@@ -2385,7 +2288,7 @@ class TestHyundaiFingerprint:
assert parser.vl["LKAS_ALT"]["ADAS_ACIAnglTqRedcGainVal"] == pytest.approx(0.0) assert parser.vl["LKAS_ALT"]["ADAS_ACIAnglTqRedcGainVal"] == pytest.approx(0.0)
assert parser.vl["LKAS_ALT"]["ADAS_StrAnglReqVal"] == pytest.approx(8.5) assert parser.vl["LKAS_ALT"]["ADAS_StrAnglReqVal"] == pytest.approx(8.5)
def test_gv70_electrified_uses_generic_lkas_status_payload(self): def test_gv70_electrified_synthesizes_lkas_status_payload(self):
CP = CarParams.new_message() CP = CarParams.new_message()
CP.carFingerprint = CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN CP.carFingerprint = CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_LKA_STEERING) CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_LKA_STEERING)
@@ -2428,11 +2331,9 @@ class TestHyundaiFingerprint:
parser.update([(1, lkas_msgs)]) parser.update([(1, lkas_msgs)])
assert parser.can_valid assert parser.can_valid
assert parser.vl["LKAS"]["HAS_LANE_SAFETY"] == 0 assert parser.vl["LKAS"]["HAS_LANE_SAFETY"] == 0
assert parser.vl["LKAS"]["DAMP_FACTOR"] == 0 assert parser.vl["LKAS"]["DAMP_FACTOR"] == 100
assert parser.vl["LKAS"]["TORQUE_REQUEST"] == 0 assert parser.vl["LKAS"]["TORQUE_REQUEST"] == 0
assert parser.vl["LKAS"]["STEER_REQ"] == 1 assert parser.vl["LKAS"]["STEER_REQ"] == 1
assert parser.vl["LKAS"]["STEER_MODE"] == 0
assert parser.vl["LKAS"]["NEW_SIGNAL_2"] == 0
CP.openpilotLongitudinalControl = True CP.openpilotLongitudinalControl = True
lfa_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LFA", 0)], can_bus.ECAN) lfa_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LFA", 0)], can_bus.ECAN)
@@ -124,7 +124,6 @@ class HyundaiStarPilotSafetyFlags(IntFlag):
class HyundaiStarPilotFlags(IntFlag): class HyundaiStarPilotFlags(IntFlag):
SPEED_LIMIT_AVAILABLE = 1 SPEED_LIMIT_AVAILABLE = 1
MAIN_CRUISE_STATE_TRACKING = 2 ** 2 MAIN_CRUISE_STATE_TRACKING = 2 ** 2
HAS_LKAS12 = 2 ** 9
class HyundaiFlags(IntFlag): class HyundaiFlags(IntFlag):
@@ -1204,7 +1203,6 @@ CANFD_SECURITYACCESS_CAR = {
} }
CANFD_UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.CANFD_NO_RADAR_DISABLE) - CANFD_SECURITYACCESS_CAR # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR CANFD_UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.CANFD_NO_RADAR_DISABLE) - CANFD_SECURITYACCESS_CAR # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR
CANFD_ANGLE_LONGITUDINAL_CAR = {CAR.KIA_EV9, CAR.HYUNDAI_IONIQ_5_PE} CANFD_ANGLE_LONGITUDINAL_CAR = {CAR.KIA_EV9, CAR.HYUNDAI_IONIQ_5_PE}
CANFD_DAW_SUPPRESSION_CAR = {CAR.HYUNDAI_IONIQ_6}
CANFD_ALT_BUTTONS_RESUME_CAR = {CAR.KIA_CARNIVAL_2025, CAR.KIA_CARNIVAL_HEV_4TH_GEN} CANFD_ALT_BUTTONS_RESUME_CAR = {CAR.KIA_CARNIVAL_2025, CAR.KIA_CARNIVAL_HEV_4TH_GEN}
CANFD_CORNER_RADAR_BSM_CAR = {CAR.HYUNDAI_IONIQ_6, CAR.HYUNDAI_IONIQ_5_PE, CAR.KIA_EV9} CANFD_CORNER_RADAR_BSM_CAR = {CAR.HYUNDAI_IONIQ_6, CAR.HYUNDAI_IONIQ_5_PE, CAR.KIA_EV9}
CANFD_RADAR_LIVE_LONGITUDINAL_CAR = { CANFD_RADAR_LIVE_LONGITUDINAL_CAR = {
-3
View File
@@ -240,9 +240,6 @@ class CarInterfaceBase(ABC):
if 0x1FA in fingerprint[CAN.ECAN]: if 0x1FA in fingerprint[CAN.ECAN]:
fp_ret.flags |= HyundaiStarPilotFlags.SPEED_LIMIT_AVAILABLE.value fp_ret.flags |= HyundaiStarPilotFlags.SPEED_LIMIT_AVAILABLE.value
if not (CP.flags & HyundaiFlags.CANFD) and 0x53E in fingerprint[2]:
fp_ret.flags |= HyundaiStarPilotFlags.HAS_LKAS12.value
fp_ret.redneckCruiseAvailable = bool(CP.flags & HyundaiFlags.NON_SCC) and not bool(CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS) fp_ret.redneckCruiseAvailable = bool(CP.flags & HyundaiFlags.NON_SCC) and not bool(CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS)
if fp_ret.redneckCruiseAvailable and params.get_bool("RedneckCruise"): if fp_ret.redneckCruiseAvailable and params.get_bool("RedneckCruise"):
fp_ret.pcmCruiseSpeed = False fp_ret.pcmCruiseSpeed = False
@@ -29,7 +29,6 @@ const LongitudinalLimits HYUNDAI_LONG_LIMITS = {
{0x340, 0, 8, .check_relay = true}, /* LKAS11 Bus 0 */ \ {0x340, 0, 8, .check_relay = true}, /* LKAS11 Bus 0 */ \
{0x4F1, scc_bus, 4, .check_relay = false}, /* CLU11 Bus 0 (radar-SCC) or 2 (camera-SCC) */ \ {0x4F1, scc_bus, 4, .check_relay = false}, /* CLU11 Bus 0 (radar-SCC) or 2 (camera-SCC) */ \
{0x485, 0, (can_refresh) ? 8 : 4, .check_relay = true}, /* LFAHDA_MFC Bus 0 */ \ {0x485, 0, (can_refresh) ? 8 : 4, .check_relay = true}, /* LFAHDA_MFC Bus 0 */ \
{0x53E, 0, 6, .check_relay = false}, /* LKAS12 replacement after camera advertises it */ \
#define HYUNDAI_LONG_COMMON_TX_MSGS(scc_bus, can_refresh) \ #define HYUNDAI_LONG_COMMON_TX_MSGS(scc_bus, can_refresh) \
HYUNDAI_COMMON_TX_MSGS(scc_bus, can_refresh) \ HYUNDAI_COMMON_TX_MSGS(scc_bus, can_refresh) \
@@ -141,12 +140,6 @@ static uint32_t hyundai_get_checksum(const CANPacket_t *msg) {
return chksum; return chksum;
} }
static void hyundai_rx_all_hook(const CANPacket_t *msg) {
if ((msg->addr == 0x53EU) && (msg->bus == 2U) && (GET_LEN(msg) == 6U)) {
hyundai_has_lkas12 = true;
}
}
static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) { static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) {
uint8_t chksum = 0; uint8_t chksum = 0;
if (msg->addr == 0x386U) { if (msg->addr == 0x386U) {
@@ -291,10 +284,6 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) {
bool tx = true; bool tx = true;
if ((msg->addr == 0x53EU) && !hyundai_has_lkas12) {
tx = false;
}
// FCA11: Block any potential actuation. The blended HDA II layout uses // FCA11: Block any potential actuation. The blended HDA II layout uses
// different static fields, but its explicit AEB/FCA request bits stay zero. // different static fields, but its explicit AEB/FCA request bits stay zero.
if (msg->addr == 0x38DU) { if (msg->addr == 0x38DU) {
@@ -706,7 +695,6 @@ static safety_config hyundai_legacy_init(uint16_t param) {
const safety_hooks hyundai_hooks = { const safety_hooks hyundai_hooks = {
.init = hyundai_init, .init = hyundai_init,
.rx = hyundai_rx_hook, .rx = hyundai_rx_hook,
.rx_all = hyundai_rx_all_hook,
.tx = hyundai_tx_hook, .tx = hyundai_tx_hook,
.get_counter = hyundai_get_counter, .get_counter = hyundai_get_counter,
.get_checksum = hyundai_get_checksum, .get_checksum = hyundai_get_checksum,
@@ -716,7 +704,6 @@ const safety_hooks hyundai_hooks = {
const safety_hooks hyundai_legacy_hooks = { const safety_hooks hyundai_legacy_hooks = {
.init = hyundai_legacy_init, .init = hyundai_legacy_init,
.rx = hyundai_rx_hook, .rx = hyundai_rx_hook,
.rx_all = hyundai_rx_all_hook,
.tx = hyundai_tx_hook, .tx = hyundai_tx_hook,
.get_counter = hyundai_get_counter, .get_counter = hyundai_get_counter,
.get_checksum = hyundai_get_checksum, .get_checksum = hyundai_get_checksum,
@@ -16,7 +16,6 @@
#define HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(a_can, e_can) \ #define HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(a_can, e_can) \
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \ HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \
{0x11A, e_can, 16, .check_relay = (e_can) == 0}, /* FR_CMR_01_10ms */ \
{0x110, a_can, 32, .check_relay = (a_can) == 0, .disable_static_blocking = true}, /* LKAS_ALT */ \ {0x110, a_can, 32, .check_relay = (a_can) == 0, .disable_static_blocking = true}, /* LKAS_ALT */ \
{0x362, a_can, 32, .check_relay = (a_can) == 0, .disable_static_blocking = true}, /* CAM_0x362 */ \ {0x362, a_can, 32, .check_relay = (a_can) == 0, .disable_static_blocking = true}, /* CAM_0x362 */ \
@@ -63,9 +63,6 @@ bool hyundai_cancel_button_enable = false;
extern bool hyundai_can_refresh_msgs; extern bool hyundai_can_refresh_msgs;
bool hyundai_can_refresh_msgs = false; bool hyundai_can_refresh_msgs = false;
extern bool hyundai_has_lkas12;
bool hyundai_has_lkas12 = false;
extern bool hyundai_elantra_hev_2024; extern bool hyundai_elantra_hev_2024;
bool hyundai_elantra_hev_2024 = false; bool hyundai_elantra_hev_2024 = false;
@@ -109,7 +106,6 @@ void hyundai_common_init(uint16_t param) {
hyundai_non_scc = GET_FLAG(param, HYUNDAI_PARAM_NON_SCC); hyundai_non_scc = GET_FLAG(param, HYUNDAI_PARAM_NON_SCC);
hyundai_cancel_button_enable = GET_FLAG(param, HYUNDAI_PARAM_CANCEL_BTN_ENABLE); hyundai_cancel_button_enable = GET_FLAG(param, HYUNDAI_PARAM_CANCEL_BTN_ENABLE);
hyundai_can_refresh_msgs = GET_FLAG(param, HYUNDAI_PARAM_CAN_REFRESH_MSGS); hyundai_can_refresh_msgs = GET_FLAG(param, HYUNDAI_PARAM_CAN_REFRESH_MSGS);
hyundai_has_lkas12 = false;
hyundai_elantra_hev_2024 = hyundai_can_refresh_msgs && hyundai_hybrid_gas_signal && hyundai_camera_scc; hyundai_elantra_hev_2024 = hyundai_can_refresh_msgs && hyundai_hybrid_gas_signal && hyundai_camera_scc;
hyundai_aol_main_lkas_sync = false; hyundai_aol_main_lkas_sync = false;
@@ -427,18 +427,6 @@ def test_hyundai_starpilot_rx_sources():
safety.safety_rx_hook(libsafety_py.make_CANPacket(0x421, 0, bytes(8))) safety.safety_rx_hook(libsafety_py.make_CANPacket(0x421, 0, bytes(8)))
def test_hyundai_lkas12_tx_requires_stock_camera_message():
safety = libsafety_py.libsafety
assert safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0) == 0
safety.init_tests()
lkas12 = libsafety_py.make_CANPacket(0x53E, 0, bytes(6))
assert not safety.safety_tx_hook(lkas12)
safety.safety_rx_hook(libsafety_py.make_CANPacket(0x53E, 2, bytes(6)))
assert safety.safety_tx_hook(lkas12)
class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety): class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety):
TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0], [0x38D, 0], [0x483, 0], [0x7D0, 0]] TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0], [0x38D, 0], [0x483, 0], [0x7D0, 0]]
@@ -568,7 +568,7 @@ class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
# TODO: Handle ICE and HEV configurations once we see cars that use the new messages # TODO: Handle ICE and HEV configurations once we see cars that use the new messages
class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase): class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
TX_MSGS = [[0x11A, 1], [0x110, 0], [0x1CF, 1], [0x362, 0]] TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362 RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362
FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]} FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]}
@@ -587,7 +587,7 @@ class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
class TestHyundaiCanfdLKASteeringAltButtonsICE(TestHyundaiCanfdLKASteeringAltEV): class TestHyundaiCanfdLKASteeringAltButtonsICE(TestHyundaiCanfdLKASteeringAltEV):
TX_MSGS = [[0x11A, 1], [0x110, 0], [0x1CF, 1], [0x1A0, 1], [0x362, 0]] TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x1A0, 1], [0x362, 0]]
GAS_MSG = ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED") GAS_MSG = ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED")
def setUp(self): def setUp(self):
@@ -691,7 +691,7 @@ class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanf
class TestHyundaiCanfdLKASteeringAltAngleLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdAngleSteering): class TestHyundaiCanfdLKASteeringAltAngleLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdAngleSteering):
TX_MSGS = [[0x11A, 1], [0x110, 0], [0x1CF, 1], [0x362, 0], [0x51, 0], [0x100, 0], [0x730, 1], [0x12a, 1], [0x160, 1], TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0], [0x51, 0], [0x100, 0], [0x730, 1], [0x12a, 1], [0x160, 1],
[0x1ba, 1], [0x1e0, 1], [0x1e5, 1], [0x31a, 1], [0x3b5, 1], [0x3c1, 1], [0x1ba, 1], [0x1e0, 1], [0x1e5, 1], [0x31a, 1], [0x3b5, 1], [0x3c1, 1],
[0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]] [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,2 +1,2 @@
extern const uint8_t gitversion[19]; extern const uint8_t gitversion[19];
const uint8_t gitversion[19] = "DEV-5fe8b174-DEBUG"; const uint8_t gitversion[19] = "DEV-3ebc6b99-DEBUG";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
DEV-5fe8b174-DEBUG DEV-3ebc6b99-DEBUG
+2 -3
View File
@@ -56,14 +56,13 @@ def build_compile_env(*, supercombo: bool = False) -> dict[str, str]:
existing_pythonpath = env.get("PYTHONPATH", "") existing_pythonpath = env.get("PYTHONPATH", "")
env["PYTHONPATH"] = f"{REPO_ROOT}{os.pathsep}{existing_pythonpath}" if existing_pythonpath else str(REPO_ROOT) env["PYTHONPATH"] = f"{REPO_ROOT}{os.pathsep}{existing_pythonpath}" if existing_pythonpath else str(REPO_ROOT)
defaults = { defaults = {
"DEBUG": "0",
"FLOAT16": "1", "FLOAT16": "1",
"IMAGE": "1" if supercombo else "2", "IMAGE": "1" if supercombo else "2",
"JIT_BATCH_SIZE": "0", "JIT_BATCH_SIZE": "0",
"NOLOCALS": "1", "NOLOCALS": "1",
"OPENPILOT_HACKS": "1", "OPENPILOT_HACKS": "1",
} | ({} if supercombo else { }
"DEBUG": "0",
})
for key, default in defaults.items(): for key, default in defaults.items():
try: try:
int(str(env.get(key)), 0) int(str(env.get(key)), 0)
+1 -1
View File
@@ -31,7 +31,7 @@ OPENPILOT_REPO = "commaai/openpilot"
RESOURCES_REPO = os.environ.get("STARPILOT_RESOURCES_REPO", "firestar5683/StarPilot-Resources") RESOURCES_REPO = os.environ.get("STARPILOT_RESOURCES_REPO", "firestar5683/StarPilot-Resources")
HF_BUCKET = os.environ.get("STARPILOT_HF_BUCKET", "StarPilot-Driving/StarPilot-Resources") HF_BUCKET = os.environ.get("STARPILOT_HF_BUCKET", "StarPilot-Driving/StarPilot-Resources")
RESOURCE_BRANCH = "Models" RESOURCE_BRANCH = "Models"
MANIFEST_VERSION = "v24" MANIFEST_VERSION = "v25"
DEFAULT_BEHAVIOR_VERSION = "v16" DEFAULT_BEHAVIOR_VERSION = "v16"
DEVICE_ROOT = "/data/openpilot" DEVICE_ROOT = "/data/openpilot"
REPOSITORY_FILE_LIMIT = 100_000_000 REPOSITORY_FILE_LIMIT = 100_000_000
+2 -2
View File
@@ -79,14 +79,14 @@ def test_runtime_scan_excludes_model_weights_but_flags_runtime_code():
def test_update_manifest_replaces_one_entry(tmp_path: Path): def test_update_manifest_replaces_one_entry(tmp_path: Path):
manifest = tmp_path / "model_names_v24.json" manifest = tmp_path / "model_names_v25.json"
manifest.write_text(json.dumps({"models": [{"id": "old"}]}) + "\n") manifest.write_text(json.dumps({"models": [{"id": "old"}]}) + "\n")
info = parse_pasted_release(RELEASE_TEXT, "bmrlnapv4", "v16") info = parse_pasted_release(RELEASE_TEXT, "bmrlnapv4", "v16")
path = update_manifest( path = update_manifest(
tmp_path, tmp_path,
info, info,
{"size": 123, "sha256": "a" * 64}, {"size": 123, "sha256": "a" * 64},
"v24", "v25",
) )
payload = json.loads(path.read_text()) payload = json.loads(path.read_text())
assert len(payload["models"]) == 2 assert len(payload["models"]) == 2
@@ -253,12 +253,12 @@ GENESIS_G70_FRICTION_CENTER_LAT = 0.28
GENESIS_G70_FRICTION_CENTER_LAT_WIDTH = 0.10 GENESIS_G70_FRICTION_CENTER_LAT_WIDTH = 0.10
GENESIS_G70_FRICTION_CALM_JERK = 0.35 GENESIS_G70_FRICTION_CALM_JERK = 0.35
GENESIS_G70_FRICTION_CALM_JERK_WIDTH = 0.10 GENESIS_G70_FRICTION_CALM_JERK_WIDTH = 0.10
GENESIS_G70_FRICTION_JERK_DEADZONE_MAX = 0.39 GENESIS_G70_FRICTION_JERK_DEADZONE_MAX = 0.30
GENESIS_G70_FRICTION_JERK_DEADZONE_LAT = 0.30 GENESIS_G70_FRICTION_JERK_DEADZONE_LAT = 0.30
GENESIS_G70_FRICTION_JERK_DEADZONE_LAT_WIDTH = 0.08 GENESIS_G70_FRICTION_JERK_DEADZONE_LAT_WIDTH = 0.08
GENESIS_G70_FRICTION_JERK_DEADZONE_SPEED = 12.0 GENESIS_G70_FRICTION_JERK_DEADZONE_SPEED = 12.0
GENESIS_G70_FRICTION_JERK_DEADZONE_SPEED_WIDTH = 3.5 GENESIS_G70_FRICTION_JERK_DEADZONE_SPEED_WIDTH = 3.5
GENESIS_G70_CENTER_OUTPUT_TAPER_MAX = 0.22 GENESIS_G70_CENTER_OUTPUT_TAPER_MAX = 0.16
GENESIS_G70_CENTER_OUTPUT_TAPER_LAT = 0.30 GENESIS_G70_CENTER_OUTPUT_TAPER_LAT = 0.30
GENESIS_G70_CENTER_OUTPUT_TAPER_LAT_WIDTH = 0.10 GENESIS_G70_CENTER_OUTPUT_TAPER_LAT_WIDTH = 0.10
GENESIS_G70_CENTER_OUTPUT_TAPER_SPEED = 18.0 GENESIS_G70_CENTER_OUTPUT_TAPER_SPEED = 18.0
@@ -288,11 +288,11 @@ GENESIS_G70_CURVE_UNWIND_LAT = 0.25
GENESIS_G70_CURVE_UNWIND_LAT_WIDTH = 0.12 GENESIS_G70_CURVE_UNWIND_LAT_WIDTH = 0.12
GENESIS_G70_CURVE_UNWIND_JERK = 0.08 GENESIS_G70_CURVE_UNWIND_JERK = 0.08
GENESIS_G70_CURVE_UNWIND_JERK_WIDTH = 0.08 GENESIS_G70_CURVE_UNWIND_JERK_WIDTH = 0.08
GENESIS_G70_UNWIND_FF_REDUCTION_MAX = 0.28 GENESIS_G70_UNWIND_FF_REDUCTION_MAX = 0.36
GENESIS_G70_UNWIND_FF_OVERSHOOT = 0.18 GENESIS_G70_UNWIND_FF_OVERSHOOT = 0.10
GENESIS_G70_UNWIND_FF_OVERSHOOT_WIDTH = 0.20 GENESIS_G70_UNWIND_FF_OVERSHOOT_WIDTH = 0.12
GENESIS_G70_UNWIND_FF_JERK = 0.10 GENESIS_G70_UNWIND_FF_JERK = 0.10
GENESIS_G70_UNWIND_FF_JERK_WIDTH = 0.13 GENESIS_G70_UNWIND_FF_JERK_WIDTH = 0.10
GENESIS_G70_UNWIND_FF_SPEED = 18.0 GENESIS_G70_UNWIND_FF_SPEED = 18.0
GENESIS_G70_UNWIND_FF_SPEED_WIDTH = 3.0 GENESIS_G70_UNWIND_FF_SPEED_WIDTH = 3.0
GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_MAX = 0.15 GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_MAX = 0.15
@@ -302,6 +302,7 @@ GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_ERROR = 0.18
GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_ERROR_WIDTH = 0.15 GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_ERROR_WIDTH = 0.15
GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK = 0.15 GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK = 0.15
GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK_WIDTH = 0.10 GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK_WIDTH = 0.10
GENESIS_G70_HIGH_SPEED_OVERSHOOT_PHASE_WEIGHT = 0.60
GENESIS_G70_ANGLE_OUTPUT_TAPER_MIN = 0.45 GENESIS_G70_ANGLE_OUTPUT_TAPER_MIN = 0.45
GENESIS_G70_ANGLE_OUTPUT_TAPER_START = 70.0 GENESIS_G70_ANGLE_OUTPUT_TAPER_START = 70.0
GENESIS_G70_ANGLE_OUTPUT_TAPER_WIDTH = 6.0 GENESIS_G70_ANGLE_OUTPUT_TAPER_WIDTH = 6.0
@@ -3237,6 +3238,8 @@ def get_genesis_g70_high_speed_error_scale(setpoint: float, measured_lateral_acc
jerk_weight = _sigmoid((abs(desired_lateral_jerk) - GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK) / jerk_weight = _sigmoid((abs(desired_lateral_jerk) - GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK) /
GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK_WIDTH) GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_JERK_WIDTH)
phase_weight = 1.0 if setpoint * desired_lateral_jerk < 0.0 else 0.45 phase_weight = 1.0 if setpoint * desired_lateral_jerk < 0.0 else 0.45
if setpoint * measured_lateral_accel > 0.0 and abs(measured_lateral_accel) > abs(setpoint):
phase_weight = max(phase_weight, GENESIS_G70_HIGH_SPEED_OVERSHOOT_PHASE_WEIGHT)
reduction = (GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_MAX * speed_weight * error_weight * reduction = (GENESIS_G70_HIGH_SPEED_ERROR_DAMPING_MAX * speed_weight * error_weight *
(0.35 + (0.65 * jerk_weight)) * phase_weight) (0.35 + (0.65 * jerk_weight)) * phase_weight)
return 1.0 - reduction return 1.0 - reduction
@@ -20,7 +20,7 @@ HONDA_ACCORD_STOP_GO_MAX_LATERAL_OFFSET = 1.25
HONDA_ACCORD_STOP_GO_MIN_MODEL_PROB = 0.95 HONDA_ACCORD_STOP_GO_MIN_MODEL_PROB = 0.95
HONDA_ACCORD_STOP_GO_ACCEL_RISE_RATE = 4.0 HONDA_ACCORD_STOP_GO_ACCEL_RISE_RATE = 4.0
HYUNDAI_ELANTRA_LEAD_FOLLOW_JERK_SCALE = 1.25 HYUNDAI_ELANTRA_LEAD_FOLLOW_JERK_SCALE = 1.25
GENESIS_GV70_ELECTRIFIED_LEAD_FOLLOW_JERK_SCALE = 1.75 GENESIS_GV70_ELECTRIFIED_LEAD_FOLLOW_JERK_SCALE = 1.35
FORD_LIGHTNING_LEAD_FOLLOW_JERK_SCALE = 1.35 FORD_LIGHTNING_LEAD_FOLLOW_JERK_SCALE = 1.35
HONDA_CRV_5G_LEAD_FOLLOW_JERK_SCALE = 1.35 HONDA_CRV_5G_LEAD_FOLLOW_JERK_SCALE = 1.35
GM_SILVERADO_EARLY_FOLLOW_MIN_EGO_SPEED = 18.0 GM_SILVERADO_EARLY_FOLLOW_MIN_EGO_SPEED = 18.0
@@ -42,7 +42,7 @@ def test_force_stop_jerk_scale_is_platform_specific():
def test_lead_follow_jerk_scale_is_platform_specific(): def test_lead_follow_jerk_scale_is_platform_specific():
assert get_lead_follow_jerk_scale(SimpleNamespace(brand="hyundai", carFingerprint="HYUNDAI_ELANTRA_2021")) == 1.25 assert get_lead_follow_jerk_scale(SimpleNamespace(brand="hyundai", carFingerprint="HYUNDAI_ELANTRA_2021")) == 1.25
assert get_lead_follow_jerk_scale(SimpleNamespace(brand="hyundai", carFingerprint="GENESIS_GV70_ELECTRIFIED_1ST_GEN")) == 1.75 assert get_lead_follow_jerk_scale(SimpleNamespace(brand="hyundai", carFingerprint="GENESIS_GV70_ELECTRIFIED_1ST_GEN")) == 1.35
assert get_lead_follow_jerk_scale(SimpleNamespace(brand="ford", carFingerprint="FORD_F_150_LIGHTNING_MK1")) == 1.35 assert get_lead_follow_jerk_scale(SimpleNamespace(brand="ford", carFingerprint="FORD_F_150_LIGHTNING_MK1")) == 1.35
assert get_lead_follow_jerk_scale(SimpleNamespace(brand="honda", carFingerprint="HONDA_CRV_5G")) == 1.35 assert get_lead_follow_jerk_scale(SimpleNamespace(brand="honda", carFingerprint="HONDA_CRV_5G")) == 1.35
assert get_lead_follow_jerk_scale(SimpleNamespace(brand="other", carFingerprint="OTHER_CAR")) == 1.0 assert get_lead_follow_jerk_scale(SimpleNamespace(brand="other", carFingerprint="OTHER_CAR")) == 1.0
+4
View File
@@ -7,6 +7,10 @@ import struct
from openpilot.system.hardware import HARDWARE, TICI from openpilot.system.hardware import HARDWARE, TICI
os.environ['GMMU'] = '0' os.environ['GMMU'] = '0'
os.environ['DEV'] = 'QCOM' if TICI else 'LLVM' os.environ['DEV'] = 'QCOM' if TICI else 'LLVM'
try:
int(os.getenv('DEBUG', '0'), 0)
except ValueError:
os.environ['DEBUG'] = '0'
from tinygrad.device import Device from tinygrad.device import Device
from tinygrad.tensor import Tensor from tinygrad.tensor import Tensor
import time import time
@@ -1 +1 @@
a77db33c2e2d6a7570dc2a4a70c2b877429ee8bd9ca5dfeda74b5a41231aaff9 driving_tinygrad.pkl 31902b114b7fb8455af694d83333a86a44112b83be662e064ffbd67e8daafe72 driving_tinygrad.pkl
+1 -1
View File
@@ -24,7 +24,7 @@ from openpilot.starpilot.common.starpilot_utilities import delete_file
from openpilot.starpilot.common.starpilot_variables import MODELS_PATH from openpilot.starpilot.common.starpilot_variables import MODELS_PATH
from openpilot.system.hardware.usb import chestnut_firmware_ready from openpilot.system.hardware.usb import chestnut_firmware_ready
MANIFEST_CANDIDATES = ("v24",) MANIFEST_CANDIDATES = ("v25",)
MODEL_NAMESPACE_SUFFIX = "3" MODEL_NAMESPACE_SUFFIX = "3"
DEFAULT_MODEL_KEY = "rdf43" DEFAULT_MODEL_KEY = "rdf43"
LOCAL_MODEL_PREFIX = "local-" LOCAL_MODEL_PREFIX = "local-"
@@ -15,12 +15,12 @@ from openpilot.starpilot.assets.model_manager import MANIFEST_CANDIDATES, ModelM
from openpilot.starpilot.common.model_versions import UNIFIED_ARTIFACT_FORMAT from openpilot.starpilot.common.model_versions import UNIFIED_ARTIFACT_FORMAT
def test_v24_is_the_only_manifest_candidate(): def test_v25_is_the_only_manifest_candidate():
assert MANIFEST_CANDIDATES == ("v24",) assert MANIFEST_CANDIDATES == ("v25",)
def test_v24_manifest_is_loaded_from_models_checkout(): def test_v25_manifest_is_loaded_from_models_checkout():
assert ModelManager._manifest_paths("v24") == ("Models/model_names_v24.json",) assert ModelManager._manifest_paths("v25") == ("Models/model_names_v25.json",)
def test_resource_sources_prefer_huggingface_then_github(monkeypatch): def test_resource_sources_prefer_huggingface_then_github(monkeypatch):
@@ -33,9 +33,9 @@ def test_resource_sources_prefer_huggingface_then_github(monkeypatch):
def test_huggingface_manifest_has_root_and_manifests_fallbacks(): def test_huggingface_manifest_has_root_and_manifests_fallbacks():
assert ModelManager._hf_manifest_paths("v24") == ( assert ModelManager._hf_manifest_paths("v25") == (
"model_names_v24.json", "model_names_v25.json",
"manifests/model_names_v24.json", "manifests/model_names_v25.json",
) )
+12 -12
View File
@@ -56,30 +56,30 @@
}, },
{ {
"name": "boot", "name": "boot",
"url": "https://files.firestar.link/x/wqn7kn631kdx/boot27.img.xz", "url": "https://files.firestar.link/x/83cmdtzb2sav/boot25.img.xz",
"fallback_urls": [ "fallback_urls": [
"https://files-east.firestar.link/x/0zzizffpkz3a/boot27.img.xz" "https://files-east.firestar.link/x/o3r7dpay7yj5/boot25.img.xz"
], ],
"hash": "173208aec963fa35a6d9a92c7ca77c5f2b49797def096f3cce05591e78b12460", "hash": "846d9e41fe0eb3543a01cb9a55a6bb540e4097dd838ada890674b654bd97a49a",
"hash_raw": "173208aec963fa35a6d9a92c7ca77c5f2b49797def096f3cce05591e78b12460", "hash_raw": "846d9e41fe0eb3543a01cb9a55a6bb540e4097dd838ada890674b654bd97a49a",
"size": 48781312, "size": 48302080,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true, "has_ab": true,
"ondevice_hash": "bc253532027b4756c09ea235b6fd794641d115b6ddbc05c417d6eb89475a22b8" "ondevice_hash": "846d9e41fe0eb3543a01cb9a55a6bb540e4097dd838ada890674b654bd97a49a"
}, },
{ {
"name": "system", "name": "system",
"url": "https://files.firestar.link/x/877rsvjzkmp8/system27.img.xz", "url": "https://files.firestar.link/x/ser56g04xioj/system25.img.xz",
"fallback_urls": [ "fallback_urls": [
"https://files-east.firestar.link/x/5ni1fkd2k4hg/system27.img.xz" "https://files-east.firestar.link/x/90fsutnuzy13/system25.img.xz"
], ],
"hash": "205dfc25b21eb236cefaabd081aa4ad6e15ccd1c9f9fc623ec29de0c1c70fb06", "hash": "f81ac06c0634ed0dadd5b4778f3b5052a2779d69669b7e70e21505c951ce6ccc",
"hash_raw": "6f204321089c7ec4bae2e8b10eda827c502e6b516e6095a3b659016b4a646d38", "hash_raw": "f81ac06c0634ed0dadd5b4778f3b5052a2779d69669b7e70e21505c951ce6ccc",
"size": 4718592000, "size": 4718592000,
"sparse": true, "sparse": false,
"full_check": false, "full_check": false,
"has_ab": true, "has_ab": true,
"ondevice_hash": "a8edcedcf4e6fb2a9af2e723a54f763f1f542fb63742cd1efc913ed30035c237" "ondevice_hash": "f81ac06c0634ed0dadd5b4778f3b5052a2779d69669b7e70e21505c951ce6ccc"
} }
] ]
+34 -29
View File
@@ -4,7 +4,7 @@ inputs:
python-version: python-version:
description: 'Python version to use' description: 'Python version to use'
required: false required: false
default: '' # if you don't set a version, the native python version will be used default: '3.14'
key: key:
description: 'Key for the python cache' description: 'Key for the python cache'
required: false required: false
@@ -41,12 +41,12 @@ inputs:
description: "Install LLVM?" description: "Install LLVM?"
required: false required: false
default: 'false' default: 'false'
tinydreno: qemu:
description: "Install tinydreno" description: "Install qemu?"
required: false required: false
default: 'false' default: 'false'
qemu: ninja:
description: "Install qemu" description: "Install ninja?"
required: false required: false
default: 'false' default: 'false'
runs: runs:
@@ -59,18 +59,18 @@ runs:
echo "OMP_NUM_THREADS=1" >> "$GITHUB_ENV" echo "OMP_NUM_THREADS=1" >> "$GITHUB_ENV"
# no buffers should be over 300MB in CI # no buffers should be over 300MB in CI
echo "MAX_BUFFER_SIZE=300000000" >> "$GITHUB_ENV" echo "MAX_BUFFER_SIZE=300000000" >> "$GITHUB_ENV"
if [[ "$RUNNER_OS" == "Linux" ]]; then
echo "VIRTUAL_ENV=/opt/venv/${{ inputs.python-version }}" >> "$GITHUB_ENV"
echo "UV_PYTHON_INSTALL_DIR=/opt/python" >> "$GITHUB_ENV"
else
echo "VIRTUAL_ENV=${{ github.workspace }}/.venv" >> "$GITHUB_ENV"
fi
- name: Set up uv - name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
with: with:
enable-cache: 'false' # see below for manual caching enable-cache: 'false' # see below for manual caching
- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@v6
if: inputs.python-version != ''
with:
python-version: ${{ inputs.python-version }}
# **** Caching packages **** # **** Caching packages ****
- name: Cache Python packages (PR) - name: Cache Python packages (PR)
@@ -109,15 +109,15 @@ runs:
if: inputs.deps != '' if: inputs.deps != ''
shell: bash shell: bash
run: | run: |
uv venv .venv uv venv --allow-existing --python ${{ inputs.python-version }} "$VIRTUAL_ENV"
DEPS="${{ inputs.deps }}" DEPS="${{ inputs.deps }}"
uv pip install --python .venv -e ".[${DEPS// /,}]" ${{ inputs.pydeps }} --torch-backend cpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/Triton-Nightly/pypi/simple/ uv pip install --python "$VIRTUAL_ENV" -e ".[${DEPS// /,}]" ${{ inputs.pydeps }} --torch-backend cpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/Triton-Nightly/pypi/simple/
- name: Install dependencies in venv (without extra) - name: Install dependencies in venv (without extra)
if: inputs.deps == '' if: inputs.deps == ''
shell: bash shell: bash
run: | run: |
uv venv .venv uv venv --allow-existing --python ${{ inputs.python-version }} "$VIRTUAL_ENV"
uv pip install --python .venv -e . ${{ inputs.pydeps }} uv pip install --python "$VIRTUAL_ENV" -e . ${{ inputs.pydeps }}
- name: Prune uv cache - name: Prune uv cache
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
shell: bash shell: bash
@@ -125,16 +125,15 @@ runs:
- name: Configure venv - name: Configure venv
shell: bash shell: bash
run: | run: |
echo "VIRTUAL_ENV=${{ github.workspace }}/.venv" >> "$GITHUB_ENV"
if [[ "$RUNNER_OS" == "Windows" ]]; then if [[ "$RUNNER_OS" == "Windows" ]]; then
echo "${{ github.workspace }}/.venv/Scripts" >> "$GITHUB_PATH" echo "$VIRTUAL_ENV/Scripts" >> "$GITHUB_PATH"
else else
echo "${{ github.workspace }}/.venv/bin" >> "$GITHUB_PATH" echo "$VIRTUAL_ENV/bin" >> "$GITHUB_PATH"
fi fi
# ******************* apt ******************* # ******************* apt *******************
- name: Setup apt - name: Setup apt
if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true') if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true' || inputs.ninja == 'true')
shell: bash shell: bash
run: | run: |
sudo mkdir -p /var/cache/apt/archives sudo mkdir -p /var/cache/apt/archives
@@ -162,7 +161,7 @@ runs:
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-20 main" | sudo tee /etc/apt/sources.list.d/llvm.list echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-20 main" | sudo tee /etc/apt/sources.list.d/llvm.list
- name: Compute Package List + Hash - name: Compute Package List + Hash
if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true') if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true' || inputs.ninja == 'true')
id: apt-pkgs id: apt-pkgs
shell: bash shell: bash
run: | run: |
@@ -187,25 +186,37 @@ runs:
if [[ "${{ inputs.qemu }}" == "true" ]]; then if [[ "${{ inputs.qemu }}" == "true" ]]; then
pkgs+=" qemu-user-static" pkgs+=" qemu-user-static"
fi fi
# **** ninja ****
if [[ "${{ inputs.ninja }}" == "true" ]]; then
pkgs+=" ninja-build"
fi
echo "pkgs=$pkgs" >> "$GITHUB_OUTPUT" echo "pkgs=$pkgs" >> "$GITHUB_OUTPUT"
echo "hash=$(echo -n "$pkgs" | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT" echo "hash=$(echo -n "$pkgs" | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
installed=true
for pkg in $pkgs; do
info=$(dpkg-query -W -f='${db:Status-Abbrev} ${Version}' "$pkg" 2> /dev/null || true)
echo "${pkg}: ${info:-not in dpkg database}"
[[ "$info" == ii* ]] || installed=false
done
echo "installed=$installed" >> "$GITHUB_OUTPUT"
- name: Cache apt (PR) - name: Cache apt (PR)
if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true') && github.event_name == 'pull_request' if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true' || inputs.ninja == 'true') && github.event_name == 'pull_request' && steps.apt-pkgs.outputs.installed == 'false'
uses: actions/cache/restore@v5 uses: actions/cache/restore@v5
with: with:
path: /var/cache/apt/archives/ path: /var/cache/apt/archives/
key: ${{ runner.os }}-${{ runner.arch }}-apt-${{ steps.apt-pkgs.outputs.hash }}-${{ env.CACHE_VERSION }} key: ${{ runner.os }}-${{ runner.arch }}-apt-${{ steps.apt-pkgs.outputs.hash }}-${{ env.CACHE_VERSION }}
- name: Cache apt - name: Cache apt
if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true') && github.event_name != 'pull_request' if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true' || inputs.ninja == 'true') && github.event_name != 'pull_request' && steps.apt-pkgs.outputs.installed == 'false'
uses: actions/cache@v5 uses: actions/cache@v5
with: with:
path: /var/cache/apt/archives/ path: /var/cache/apt/archives/
key: ${{ runner.os }}-${{ runner.arch }}-apt-${{ steps.apt-pkgs.outputs.hash }}-${{ env.CACHE_VERSION }} key: ${{ runner.os }}-${{ runner.arch }}-apt-${{ steps.apt-pkgs.outputs.hash }}-${{ env.CACHE_VERSION }}
- name: Run apt Update + Install - name: Run apt Update + Install
if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true') if: runner.os == 'Linux' && (inputs.opencl == 'true' || inputs.amd == 'true' || inputs.webgpu == 'true' || inputs.llvm == 'true' || inputs.qemu == 'true' || inputs.ninja == 'true') && steps.apt-pkgs.outputs.installed == 'false'
shell: bash shell: bash
run: | run: |
sudo apt -qq update || true sudo apt -qq update || true
@@ -277,12 +288,6 @@ runs:
shell: bash shell: bash
run: brew install llvm@20 run: brew install llvm@20
# *** tinydreno ***
- name: Install tinydreno (linux)
if: inputs.tinydreno == 'true' && runner.os == 'Linux'
shell: bash
run: sudo curl -fL https://github.com/sirhcm/tinydreno/raw/refs/heads/master/libllvm-qcom.so -o /usr/lib/libllvm-qcom.so
# *** OpenCL *** # *** OpenCL ***
- name: Install rusticl - name: Install rusticl
if: inputs.opencl == 'true' if: inputs.opencl == 'true'
+4 -43
View File
@@ -35,15 +35,15 @@ jobs:
key: 'autogen' key: 'autogen'
amd: 'true' amd: 'true'
llvm: 'true' llvm: 'true'
pydeps: 'pyyaml mako' deps: 'autogen'
- name: Install autogen support packages - name: Install autogen support packages
run: sudo apt-get install -y --no-install-recommends libclang-20-dev llvm-20-dev hip-dev libusb-1.0-0-dev libdrm-dev liburing-dev run: sudo apt-get install -y --no-install-recommends libclang-20-dev llvm-20-dev hip-dev libusb-1.0-0-dev libdrm-dev liburing-dev
- name: Regenerate autogen files - name: Regenerate autogen files
run: | run: |
find tinygrad/runtime/autogen -type f -name "*.py" -not -path "*/amd/*" -not -name "__init__.py" -not -name "comgr.py" -not -name "metal.py" -not -name "iokit.py" -not -name "corefoundation.py" -not -name "libclang.py" -delete find tinygrad/runtime/autogen -type f -name "*.py" -not -path "*/amd/*" -not -name "__init__.py" -not -name "metal.py" -not -name "iokit.py" -not -name "corefoundation.py" -not -name "libclang.py" -delete
python3 -c "from tinygrad.runtime.autogen import opencl" python3 -c "from tinygrad.runtime.autogen import opencl"
python3 -c "from tinygrad.runtime.autogen import cuda, nvrtc, nvjitlink, nv_570, nv_580, nv_610, nv" python3 -c "from tinygrad.runtime.autogen import cuda, nvrtc, nvjitlink, nv_570, nv_580, nv_610, nv"
python3 -c "from tinygrad.runtime.autogen import comgr_3, hsa, hip, amd_gpu, sqtt, rocprof, amdgpu_kd, amdgpu_drm" python3 -c "from tinygrad.runtime.autogen import comgr, comgr_3, hsa, hip, amd_gpu, sqtt, rocprof, amdgpu_kd, amdgpu_drm"
python3 -c "from tinygrad.runtime.autogen.am import *" python3 -c "from tinygrad.runtime.autogen.am import *"
python3 -c "from tinygrad.runtime.autogen.nv_regs import *" python3 -c "from tinygrad.runtime.autogen.nv_regs import *"
python3 -c "from tinygrad.runtime.autogen import libc, kfd, io_uring, pci, vfio" python3 -c "from tinygrad.runtime.autogen import libc, kfd, io_uring, pci, vfio"
@@ -54,7 +54,7 @@ jobs:
python3 -c "from tinygrad.runtime.autogen import mesa" python3 -c "from tinygrad.runtime.autogen import mesa"
python3 -c "from tinygrad.runtime.autogen import avcodec" python3 -c "from tinygrad.runtime.autogen import avcodec"
python3 -c "from tinygrad.runtime.autogen import llvm_qcom" python3 -c "from tinygrad.runtime.autogen import llvm_qcom"
python3 -c "from tinygrad.runtime.autogen import mlx5" python3 -c "from tinygrad.runtime.autogen import mlx5, bnxt"
python3 -c "from tinygrad.runtime.autogen import ggml_common" python3 -c "from tinygrad.runtime.autogen import ggml_common"
REGEN=1 python3 -c "from tinygrad.runtime.autogen import libclang" REGEN=1 python3 -c "from tinygrad.runtime.autogen import libclang"
- name: Check for differences - name: Check for differences
@@ -102,42 +102,3 @@ jobs:
with: with:
name: autogen-macos-patch name: autogen-macos-patch
path: autogen-macos.patch path: autogen-macos.patch
autogen-comgr-2:
name: In-tree Autogen (comgr 2)
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: 'autogen-comgr'
- name: Install autogen support packages
run: |
wget https://repo.radeon.com/rocm/rocm.gpg.key -O - | gpg --dearmor | sudo tee /etc/apt/keyrings/rocm.gpg > /dev/null
sudo tee /etc/apt/sources.list.d/rocm.list <<EOF
deb [arch=amd64 signed-by=/etc/apt/keyrings/rocm.gpg] https://repo.radeon.com/rocm/apt/6.2 $(lsb_release -cs) main
EOF
echo -e 'Package: *\nPin: release o=repo.radeon.com\nPin-Priority: 600' | sudo tee /etc/apt/preferences.d/rocm-pin-600
sudo apt -qq update || true
sudo apt-get install -y --no-install-recommends libclang-20-dev comgr
- name: Regenerate autogen files
run: |
rm tinygrad/runtime/autogen/comgr.py
python3 -c "from tinygrad.runtime.autogen import comgr"
- name: Check for differences
run: |
if ! git diff --quiet; then
git diff
git diff > autogen-comgr2.patch
echo "Autogen mismatch detected. Patch available at: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}#artifacts"
exit 1
fi
- name: Upload patch artifact
if: failure()
uses: actions/upload-artifact@v7
with:
name: autogen-comgr2-patch
path: autogen-comgr2.patch
+148 -127
View File
@@ -88,13 +88,13 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
dev: ['METAL', 'AMD', 'NV'] dev: ['METAL', 'AMD', 'NV']
timeout-minutes: 60 timeout-minutes: 30
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
env: env:
DEV: ${{ matrix.dev }} DEV: ${{ matrix.dev }}
HCQ2: ${{ matrix.dev == 'AMD' && '1' || '0' }} HCQ2: '0'
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -102,16 +102,11 @@ jobs:
- name: Setup (AMD) - name: Setup (AMD)
if: ${{ matrix.dev == 'AMD' }} if: ${{ matrix.dev == 'AMD' }}
run: | run: |
./extra/amdpci/setup_python_cap.sh ./extra/hcq/hcq_smi.py amd rmmod --expect
./extra/hcq/hcq_smi.py amd rmmod ./extra/hcq/hcq_smi.py amd kill_pids --sudoless
./extra/hcq/hcq_smi.py amd kill_pids
- name: Setup (NV) - name: Setup (NV)
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: sudo lsof -tQ /dev/nvidia* | { xargs -r sudo kill -9 || true; } run: lsof -tQ /dev/nvidia* | { xargs -r kill -9 || true; }
- name: Symlink models and datasets
run: |
mkdir -p weights
ln -s /raid/weights/LLaMA-3 weights/LLaMA-3
- name: setup staging db - name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging' if: github.ref == 'refs/heads/update_benchmark_staging'
run: | run: |
@@ -121,18 +116,14 @@ jobs:
run: python3 test/external/process_replay/reset.py run: python3 test/external/process_replay/reset.py
- name: Run llama3.2 - name: Run llama3.2
run: BENCHMARK_LOG=llama32_3b-f16 JITBEAM=2 IGNORE_BEAM_CACHE=1 python3 -m tinygrad.llm -m llama3.2:3b-f16 --benchmark --warmup run: BENCHMARK_LOG=llama32_3b-f16 JITBEAM=2 IGNORE_BEAM_CACHE=1 python3 -m tinygrad.llm -m llama3.2:3b-f16 --benchmark --warmup
- name: Run qwen3.6 - name: Run qwen3.8
# qwen3.6:35b-a3b doesn't fit on mac # qwen3.8:27b doesn't fit on mac
if: ${{ matrix.dev != 'METAL' }} if: ${{ matrix.dev != 'METAL' }}
run: BENCHMARK_LOG=qwen36_35b-a3b JITBEAM=2 IGNORE_BEAM_CACHE=1 python3 -m tinygrad.llm -m qwen3.6:35b-a3b --benchmark --warmup run: BENCHMARK_LOG=qwen38_27b JITBEAM=2 IGNORE_BEAM_CACHE=1 python3 -m tinygrad.llm -m qwen3.8:27b --benchmark --warmup
- name: Run olmoe - name: Run olmoe
# just metal for now # just metal for now
if: ${{ matrix.dev == 'METAL' }} if: ${{ matrix.dev == 'METAL' }}
run: BENCHMARK_LOG=olmoe JITBEAM=2 IGNORE_BEAM_CACHE=1 python3 -m tinygrad.llm -m olmoe --benchmark --warmup run: BENCHMARK_LOG=olmoe JITBEAM=2 IGNORE_BEAM_CACHE=1 python3 -m tinygrad.llm -m olmoe --benchmark --warmup
- name: Run LLaMA-3 8B on 4 GPUs with BEAM
# only run on machines with multiple gpus
if: ${{ matrix.dev != 'METAL' }}
run: BENCHMARK_LOG=llama3_beam_4gpu JITBEAM=2 IGNORE_BEAM_CACHE=1 CAPTURE_PROCESS_REPLAY=0 python3 examples/llama3.py --size 8B --shard 4 --model weights/LLaMA-3/8B-SF-DPO/ --benchmark --temperature 0
- name: Run process replay tests - name: Run process replay tests
uses: ./.github/actions/process-replay uses: ./.github/actions/process-replay
@@ -143,13 +134,13 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
dev: ['METAL', 'AMD', 'NV'] dev: ['METAL', 'AMD', 'NV']
timeout-minutes: 60 timeout-minutes: 10
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
env: env:
DEV: ${{ matrix.dev }} DEV: ${{ matrix.dev }}
HCQ2: ${{ matrix.dev == 'AMD' && '1' || '0' }} HCQ2: '0'
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -157,12 +148,11 @@ jobs:
- name: Setup (AMD) - name: Setup (AMD)
if: ${{ matrix.dev == 'AMD' }} if: ${{ matrix.dev == 'AMD' }}
run: | run: |
./extra/amdpci/setup_python_cap.sh ./extra/hcq/hcq_smi.py amd rmmod --expect
./extra/hcq/hcq_smi.py amd rmmod ./extra/hcq/hcq_smi.py amd kill_pids --sudoless
./extra/hcq/hcq_smi.py amd kill_pids
- name: Setup (NV) - name: Setup (NV)
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: sudo lsof -tQ /dev/nvidia* | { xargs -r sudo kill -9 || true; } run: lsof -tQ /dev/nvidia* | { xargs -r kill -9 || true; }
- name: setup staging db - name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging' if: github.ref == 'refs/heads/update_benchmark_staging'
run: | run: |
@@ -182,10 +172,6 @@ jobs:
# slow on metal # slow on metal
if: ${{ matrix.dev != 'METAL' }} if: ${{ matrix.dev != 'METAL' }}
run: time BENCHMARK_LOG=cifar DEFAULT_FLOAT=HALF STEPS=1000 TARGET_EVAL_ACC_PCT=93.0 python3 examples/hlb_cifar10.py run: time BENCHMARK_LOG=cifar DEFAULT_FLOAT=HALF STEPS=1000 TARGET_EVAL_ACC_PCT=93.0 python3 examples/hlb_cifar10.py
- name: Run full CIFAR training steps w 6 GPUS
# only run on machines with multiple gpus
if: ${{ matrix.dev != 'METAL' }}
run: time BENCHMARK_LOG=cifar_6gpu CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF STEPS=350 BS=1536 GPUS=6 TARGET_EVAL_ACC_PCT=93.0 python3 examples/hlb_cifar10.py
- name: Run process replay tests - name: Run process replay tests
uses: ./.github/actions/process-replay uses: ./.github/actions/process-replay
@@ -196,13 +182,13 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
dev: ['AMD', 'NV'] dev: ['AMD', 'NV']
timeout-minutes: 60 timeout-minutes: 5
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
env: env:
DEV: ${{ matrix.dev }} DEV: ${{ matrix.dev }}
HCQ2: ${{ matrix.dev == 'AMD' && '1' || '0' }} HCQ2: '0'
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -210,12 +196,11 @@ jobs:
- name: Setup (AMD) - name: Setup (AMD)
if: ${{ matrix.dev == 'AMD' }} if: ${{ matrix.dev == 'AMD' }}
run: | run: |
./extra/amdpci/setup_python_cap.sh ./extra/hcq/hcq_smi.py amd rmmod --expect
./extra/hcq/hcq_smi.py amd rmmod ./extra/hcq/hcq_smi.py amd kill_pids --sudoless
./extra/hcq/hcq_smi.py amd kill_pids
- name: Setup (NV) - name: Setup (NV)
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: sudo lsof -tQ /dev/nvidia* | { xargs -r sudo kill -9 || true; } run: lsof -tQ /dev/nvidia* | { xargs -r kill -9 || true; }
- name: Symlink models and datasets - name: Symlink models and datasets
run: | run: |
mkdir -p extra/datasets mkdir -p extra/datasets
@@ -227,15 +212,8 @@ jobs:
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: reset process replay - name: reset process replay
run: test/external/process_replay/reset.py run: test/external/process_replay/reset.py
- name: Run MLPerf resnet eval on training data
run: time BENCHMARK_LOG=resnet_eval MODEL=resnet python3 examples/mlperf/model_eval.py
- name: Run 10 MLPerf ResNet50 training steps (1 gpu) - name: Run 10 MLPerf ResNet50 training steps (1 gpu)
run: BENCHMARK_LOG=resnet_10steps DEFAULT_FLOAT=HALF BENCHMARK=10 BS=256 GPUS=1 MODEL=resnet python3 examples/mlperf/model_train.py run: BENCHMARK_LOG=resnet_10steps DEFAULT_FLOAT=HALF BENCHMARK=10 BS=256 GPUS=1 MODEL=resnet python3 examples/mlperf/model_train.py
- name: Run 10 MLPerf ResNet50 training steps (6 gpu)
run: BENCHMARK_LOG=resnet_10steps_6gpu CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=1536 GPUS=6 MODEL=resnet python3 examples/mlperf/model_train.py
- name: Run 10 MLPerf Bert training steps (6 gpu)
# TODO: remove BERT_LAYERS once scheduler is fast
run: BENCHMARK_LOG=bert_10steps_6gpu CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=72 GPUS=6 BERT_LAYERS=2 MODEL=bert python3 examples/mlperf/model_train.py
- name: Run process replay tests - name: Run process replay tests
uses: ./.github/actions/process-replay uses: ./.github/actions/process-replay
@@ -246,13 +224,13 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
dev: ['METAL', 'AMD', 'NV'] dev: ['METAL', 'AMD', 'NV']
timeout-minutes: 60 timeout-minutes: 15
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
env: env:
DEV: ${{ matrix.dev }} DEV: ${{ matrix.dev }}
HCQ2: ${{ matrix.dev == 'AMD' && '1' || '0' }} HCQ2: '0'
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -260,12 +238,11 @@ jobs:
- name: Setup (AMD) - name: Setup (AMD)
if: ${{ matrix.dev == 'AMD' }} if: ${{ matrix.dev == 'AMD' }}
run: | run: |
./extra/amdpci/setup_python_cap.sh ./extra/hcq/hcq_smi.py amd rmmod --expect
./extra/hcq/hcq_smi.py amd rmmod ./extra/hcq/hcq_smi.py amd kill_pids --sudoless
./extra/hcq/hcq_smi.py amd kill_pids
- name: Setup (NV) - name: Setup (NV)
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: sudo lsof -tQ /dev/nvidia* | { xargs -r sudo kill -9 || true; } run: lsof -tQ /dev/nvidia* | { xargs -r kill -9 || true; }
- name: setup staging db - name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging' if: github.ref == 'refs/heads/update_benchmark_staging'
run: | run: |
@@ -285,6 +262,59 @@ jobs:
- name: Run process replay tests - name: Run process replay tests
uses: ./.github/actions/process-replay uses: ./.github/actions/process-replay
multigpubenchmark:
name: Multi-GPU Benchmarks (DEV=${{ matrix.dev }})
runs-on: [self-hosted, "${{ matrix.dev == 'AMD' && 'tinybox' || 'tinyboxgreen' }}"]
strategy:
fail-fast: false
matrix:
dev: ['AMD', 'NV']
timeout-minutes: 20
defaults:
run:
shell: bash -e -o pipefail {0}
env:
DEV: ${{ matrix.dev }}
HCQ2: '0'
if: github.repository_owner == 'tinygrad'
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Setup (AMD)
if: ${{ matrix.dev == 'AMD' }}
run: |
./extra/hcq/hcq_smi.py amd rmmod --expect
./extra/hcq/hcq_smi.py amd kill_pids --sudoless
- name: Setup (NV)
if: ${{ matrix.dev == 'NV' }}
run: lsof -tQ /dev/nvidia* | { xargs -r kill -9 || true; }
- name: Symlink models and datasets
run: |
mkdir -p weights
mkdir -p extra/datasets
ln -s /raid/weights/LLaMA-3 weights/LLaMA-3
ln -s /raid/datasets/imagenet extra/datasets/imagenet
- name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging'
run: |
echo "CACHEDB=/tmp/staging.db" >> $GITHUB_ENV
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: reset process replay
run: python3 test/external/process_replay/reset.py
- name: Run LLaMA-3 8B on 4 GPUs with BEAM
run: BENCHMARK_LOG=llama3_beam_4gpu JITBEAM=2 IGNORE_BEAM_CACHE=1 CAPTURE_PROCESS_REPLAY=0 python3 examples/llama3.py --size 8B --shard 4 --model weights/LLaMA-3/8B-SF-DPO/ --benchmark --temperature 0
- name: Run full CIFAR training steps w 6 GPUS
run: time BENCHMARK_LOG=cifar_6gpu CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF STEPS=350 BS=1536 GPUS=6 TARGET_EVAL_ACC_PCT=93.0 python3 examples/hlb_cifar10.py
- name: Run MLPerf resnet eval on training data
run: time BENCHMARK_LOG=resnet_eval MODEL=resnet python3 examples/mlperf/model_eval.py
- name: Run 10 MLPerf ResNet50 training steps (6 gpu)
run: BENCHMARK_LOG=resnet_10steps_6gpu CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=1536 GPUS=6 MODEL=resnet python3 examples/mlperf/model_train.py
- name: Run 10 MLPerf Bert training steps (6 gpu)
# TODO: remove BERT_LAYERS once scheduler is fast
run: BENCHMARK_LOG=bert_10steps_6gpu CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=72 GPUS=6 BERT_LAYERS=2 MODEL=bert python3 examples/mlperf/model_train.py
- name: Run process replay tests
uses: ./.github/actions/process-replay
tests: tests:
name: Tests (DEV=${{ matrix.dev }}) name: Tests (DEV=${{ matrix.dev }})
runs-on: [self-hosted, "${{ matrix.dev == 'METAL' && 'macOS' || matrix.dev == 'AMD' && 'tinybox' || 'tinyboxgreen' }}"] runs-on: [self-hosted, "${{ matrix.dev == 'METAL' && 'macOS' || matrix.dev == 'AMD' && 'tinybox' || 'tinyboxgreen' }}"]
@@ -292,7 +322,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
dev: ['METAL', 'AMD', 'NV'] dev: ['METAL', 'AMD', 'NV']
timeout-minutes: 60 timeout-minutes: 10
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
@@ -305,12 +335,11 @@ jobs:
- name: Setup (AMD) - name: Setup (AMD)
if: ${{ matrix.dev == 'AMD' }} if: ${{ matrix.dev == 'AMD' }}
run: | run: |
./extra/amdpci/setup_python_cap.sh ./extra/hcq/hcq_smi.py amd rmmod --expect
./extra/hcq/hcq_smi.py amd rmmod ./extra/hcq/hcq_smi.py amd kill_pids --sudoless
./extra/hcq/hcq_smi.py amd kill_pids
- name: Setup (NV) - name: Setup (NV)
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: sudo lsof -tQ /dev/nvidia* | { xargs -r sudo kill -9 || true; } run: lsof -tQ /dev/nvidia* | { xargs -r kill -9 || true; }
- name: setup staging db - name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging' if: github.ref == 'refs/heads/update_benchmark_staging'
run: | run: |
@@ -374,7 +403,7 @@ jobs:
run: python test/external/external_benchmark_multitensor_allreduce.py run: python test/external/external_benchmark_multitensor_allreduce.py
- name: HEVC Decode Benchmark - name: HEVC Decode Benchmark
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: VALIDATE=1 MAX_FRAMES=100 ASSERT_FPS=1400 JITBEAM=1 PYTHONPATH=. python3 extra/hevc/decode.py run: IGNORE_BEAM_CACHE=1 VALIDATE=1 MAX_FRAMES=100 ASSERT_FPS=1400 JITBEAM=1 PYTHONPATH=. python3 extra/hevc/decode.py
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v7
if: ${{ matrix.dev != 'AMD' }} if: ${{ matrix.dev != 'AMD' }}
with: with:
@@ -387,7 +416,7 @@ jobs:
testusbgpu: testusbgpu:
name: UsbGPU Benchmark name: UsbGPU Benchmark
runs-on: [self-hosted, macOS] runs-on: [self-hosted, macOS]
timeout-minutes: 10 timeout-minutes: 3
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
@@ -402,32 +431,66 @@ jobs:
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: Kill stale pids - name: Kill stale pids
run: | run: |
PYTHONPATH=. ./extra/hcq/hcq_smi.py amd kill_pids ./extra/hcq/hcq_smi.py amd kill_pids --sudoless
PYTHONPATH=. ./extra/hcq/hcq_smi.py nv kill_pids ./extra/hcq/hcq_smi.py nv kill_pids --sudoless
# since sudo is required for usbgpu on macos, do not write bytecode, as some of the files are owned by root
- name: UsbGPU boot time - name: UsbGPU boot time
run: sudo -E PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. GMMU=0 DEBUG=2 AM_RESET=1 DEV=USB+AMD time python3.11 test/test_tiny.py TestTiny.test_plus run: GMMU=0 DEBUG=2 AM_RESET=1 DEV=USB+AMD time python3.11 test/test_tiny.py TestTiny.test_plus
- name: UsbGPU tiny tests - name: UsbGPU tiny tests
run: sudo -E PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. GMMU=0 DEV=USB+AMD python3.11 test/test_tiny.py run: GMMU=0 DEV=USB+AMD python3.11 test/test_tiny.py
- name: UsbGPU copy speeds - name: UsbGPU copy speeds
run: sudo -E PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. GMMU=0 DEV=USB+AMD python3.11 test/external/external_test_usb_asm24.py TestDevCopySpeeds run: SIZE=64000000 PYTHONPATH=. GMMU=0 DEV=USB+AMD python3.11 test/external/external_test_usb_asm24.py TestDevCopySpeeds
#- name: UsbGPU openpilot test
# run: sudo -E PYTHONPATH=. GMMU=0 DEV=USB+AMD GRAPH_ONE_KERNEL=1 python3.11 examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/9118973ed03c1ae1d40cf69a29507ec2cc78efd7/selfdrive/modeld/models/supercombo.onnx
- name: UsbGPU (USB4/TB) install script - name: UsbGPU (USB4/TB) install script
run: PYTHONPATH=. sh extra/setup_tinygpu_osx.sh run: sh extra/setup_tinygpu_osx.sh
- name: UsbGPU (USB4/TB) boot time - name: UsbGPU (USB4/TB) boot time
run: PYTHONPATH=. DEBUG=3 DEV=PCI+NV:NAK time python3.11 test/test_tiny.py TestTiny.test_plus run: DEBUG=3 DEV=PCI+NV:NAK time python3.11 test/test_tiny.py TestTiny.test_plus
- name: UsbGPU (USB4/TB) tiny tests - name: UsbGPU (USB4/TB) tiny tests
run: PYTHONPATH=. DEV=PCI+NV:NAK python3.11 test/test_tiny.py run: DEV=PCI+NV:NAK python3.11 test/test_tiny.py
testcommalatest: testcomma:
name: comma Benchmark (0.11.2) strategy:
runs-on: [self-hosted, Linux, comma] matrix:
timeout-minutes: 12 dev: ['QCOM', 'QCOM:IR3']
version: ['0.11.0', '0.11.2']
model: ['vision', 'policy', 'supercombo', 'dmonitoring']
# exclude non-existent models
exclude: [{ version: '0.11.0', model: supercombo }, { version: '0.11.2', model: vision }, { version: '0.11.2', model: policy }]
include:
- version: '0.11.0'
model: vision
url: https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/driving_vision.onnx
timing: 18
- version: '0.11.0'
model: policy
url: https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/driving_policy.onnx
timing: 3.4
- version: '0.11.0'
model: dmonitoring
url: https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/dmonitoring_model.onnx
timing: 13
- version: '0.11.2'
model: supercombo
url: https://gitlab.com/commaai/openpilot-lfs.git/gitlab-lfs/objects/433f85f956837606ad1f1cbee4aa7e2158ad23c768dea914b20436c97232741b
timing: 28
- dev: QCOM:IR3
version: '0.11.2'
model: supercombo
timing: 29
- version: '0.11.2'
model: dmonitoring
url: https://gitlab.com/commaai/openpilot-lfs.git/gitlab-lfs/objects/3e7b31dfbc0a5234f1baf196513b77fc6af12204b8a8ffe8ee0417e48352f316
timing: 12.5
fail-fast: false
name: openpilot ${{ matrix.version }} compile3 ${{ matrix.model }} (DEV=${{ matrix.dev }})
runs-on: [self-hosted, Linux, comma4]
timeout-minutes: 5
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
env:
DEV: ${{ matrix.dev }}
ASSERT_MIN_STEP_TIME: ${{ matrix.timing }}
BENCHMARK_LOG: ${{ matrix.dev == 'QCOM:IR3' && 'ir3_' || '' }}openpilot_${{ matrix.version }}_${{ matrix.model }}
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v6 uses: actions/checkout@v6
@@ -438,45 +501,10 @@ jobs:
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: reset process replay - name: reset process replay
run: test/external/process_replay/reset.py run: test/external/process_replay/reset.py
- name: openpilot compile3 0.11.2 supercombo - name: compile
run: BENCHMARK_LOG=openpilot_0_11_2_supercombo PYTHONPATH="." ASSERT_MIN_STEP_TIME=26 DEV=QCOM FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://gitlab.com/commaai/openpilot-lfs.git/gitlab-lfs/objects/433f85f956837606ad1f1cbee4aa7e2158ad23c768dea914b20436c97232741b run: FLOAT16=1 IMAGE=1 taskset -c 4-7 python3 examples/openpilot/compile3.py ${{ matrix.url }} openpilot.pkl
- name: openpilot compile3 0.11.2 supercombo (from pickle) - name: run pickle
run: BENCHMARK_LOG=openpilot_0_11_2_supercombo_run_pickle RUN_PICKLE=1 PYTHONPATH="." ASSERT_MIN_STEP_TIME=26 DEV=QCOM taskset -c 4-7 python3 examples/openpilot/compile3.py run: BENCHMARK_LOG="${BENCHMARK_LOG}_run_pickle" RUN_PICKLE=1 taskset -c 4-7 python3 examples/openpilot/compile3.py - openpilot.pkl
- name: IR3 openpilot compile3 0.11.2 supercombo
run: BENCHMARK_LOG=ir3_openpilot_0_11_2_supercombo PYTHONPATH="." ASSERT_MIN_STEP_TIME=41 DEV=QCOM:IR3 FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://gitlab.com/commaai/openpilot-lfs.git/gitlab-lfs/objects/433f85f956837606ad1f1cbee4aa7e2158ad23c768dea914b20436c97232741b
- name: openpilot compile3 0.11.2 dmonitoring
run: BENCHMARK_LOG=openpilot_0_11_2_dmonitoring PYTHONPATH="." ASSERT_MIN_STEP_TIME=11 DEV=QCOM FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://gitlab.com/commaai/openpilot-lfs.git/gitlab-lfs/objects/3e7b31dfbc0a5234f1baf196513b77fc6af12204b8a8ffe8ee0417e48352f316
- name: Run process replay tests
uses: ./.github/actions/process-replay
testcommaold:
name: comma Benchmark (0.11.0)
runs-on: [self-hosted, Linux, comma]
timeout-minutes: 12
defaults:
run:
shell: bash -e -o pipefail {0}
if: github.repository_owner == 'tinygrad'
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging'
run: |
echo "CACHEDB=/tmp/staging.db" >> $GITHUB_ENV
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: reset process replay
run: test/external/process_replay/reset.py
- name: openpilot compile3 0.11.0 driving_vision
run: BENCHMARK_LOG=openpilot_0_11_0_vision PYTHONPATH="." ASSERT_MIN_STEP_TIME=17 DEV=QCOM FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/driving_vision.onnx
- name: openpilot compile3 0.11.0 driving_vision (from pickle)
run: BENCHMARK_LOG=openpilot_0_11_0_vision_run_pickle RUN_PICKLE=1 PYTHONPATH="." ASSERT_MIN_STEP_TIME=17 DEV=QCOM taskset -c 4-7 python3 examples/openpilot/compile3.py
- name: IR3 openpilot compile3 0.11.0 driving_vision
run: BENCHMARK_LOG=ir3_openpilot_0_11_0_vision PYTHONPATH="." ASSERT_MIN_STEP_TIME=18 DEV=QCOM:IR3 FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/driving_vision.onnx
- name: openpilot compile3 0.11.0 driving_policy
run: BENCHMARK_LOG=openpilot_0_11_0_policy PYTHONPATH="." ASSERT_MIN_STEP_TIME=3.2 DEV=QCOM FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/driving_policy.onnx
- name: openpilot compile3 0.11.0 dmonitoring
run: BENCHMARK_LOG=openpilot_0_11_0_dmonitoring PYTHONPATH="." ASSERT_MIN_STEP_TIME=11 DEV=QCOM FLOAT16=1 IMAGE=1 NOLOCALS=1 taskset -c 4-7 python3 examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/v0.11.0/selfdrive/modeld/models/dmonitoring_model.onnx
- name: Run process replay tests - name: Run process replay tests
uses: ./.github/actions/process-replay uses: ./.github/actions/process-replay
@@ -489,15 +517,6 @@ jobs:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
steps: steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: setup staging db
if: github.ref == 'refs/heads/update_benchmark_staging'
run: |
echo "CACHEDB=/tmp/staging.db" >> $GITHUB_ENV
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: reset process replay
run: test/external/process_replay/reset.py
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: setup staging db - name: setup staging db
@@ -510,8 +529,8 @@ jobs:
- name: benchmark MobileNetV2 on DSP - name: benchmark MobileNetV2 on DSP
run: | run: |
# generate quantized weights # generate quantized weights
ln -s /data/home/tiny/tinygrad/extra/datasets/imagenet extra/datasets/imagenet ln -s ~/tinygrad/extra/datasets/imagenet extra/datasets/imagenet
ln -s /data/home/tiny/tinygrad/testsig-*.so . ln -s ~/tinygrad/testsig-*.so .
PYTHONPATH=. DEV=CPU QUANT=1 CNT=0 python3 examples/test_onnx_imagenet.py https://github.com/xamcat/mobcat-samples/raw/refs/heads/master/onnx_runtime/InferencingSample/InferencingSample/mobilenetv2-7.onnx /tmp/model.quant.onnx PYTHONPATH=. DEV=CPU QUANT=1 CNT=0 python3 examples/test_onnx_imagenet.py https://github.com/xamcat/mobcat-samples/raw/refs/heads/master/onnx_runtime/InferencingSample/InferencingSample/mobilenetv2-7.onnx /tmp/model.quant.onnx
# benchmark on DSP with NOOPT=1, the devectorizer has issues # benchmark on DSP with NOOPT=1, the devectorizer has issues
PYTHONPATH=. DEV=DSP NOOPT=1 CNT=2 DEBUG=2 python3 examples/test_onnx_imagenet.py /tmp/model.quant.onnx PYTHONPATH=. DEV=DSP NOOPT=1 CNT=2 DEBUG=2 python3 examples/test_onnx_imagenet.py /tmp/model.quant.onnx
@@ -521,7 +540,7 @@ jobs:
testcommausbgpubenchmark: testcommausbgpubenchmark:
name: UsbGPU Benchmark (comma) name: UsbGPU Benchmark (comma)
runs-on: [self-hosted, Linux, comma4] runs-on: [self-hosted, Linux, comma4]
timeout-minutes: 20 timeout-minutes: 10
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
@@ -541,7 +560,7 @@ jobs:
- name: openpilot run_pickle big_driving_supercombo - name: openpilot run_pickle big_driving_supercombo
run: BENCHMARK_LOG=usbgpu_openpilot_big_driving_supercombo_run_pickle RUN_PICKLE=1 PICKLE_OOB=1 PYTHONPATH="." GMMU=0 DEV=USB+AMD ASSERT_MIN_STEP_TIME=50 python3 examples/openpilot/compile3.py - openpilot.pkl run: BENCHMARK_LOG=usbgpu_openpilot_big_driving_supercombo_run_pickle RUN_PICKLE=1 PICKLE_OOB=1 PYTHONPATH="." GMMU=0 DEV=USB+AMD ASSERT_MIN_STEP_TIME=50 python3 examples/openpilot/compile3.py - openpilot.pkl
- name: Test copy speeds - name: Test copy speeds
run: SIZE=64e6 PYTHONPATH=. GMMU=0 DEV=USB+AMD python3 test/external/external_test_usb_asm24.py TestDevCopySpeeds run: SIZE=64000000 PYTHONPATH=. GMMU=0 DEV=USB+AMD python3 test/external/external_test_usb_asm24.py TestDevCopySpeeds
driverbenchmarks: driverbenchmarks:
name: PCI Driver Benchmark (DEV=${{ matrix.dev }}) name: PCI Driver Benchmark (DEV=${{ matrix.dev }})
@@ -550,7 +569,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
dev: ['AMD', 'NV'] dev: ['AMD', 'NV']
timeout-minutes: 20 timeout-minutes: 5
defaults: defaults:
run: run:
shell: bash -e -o pipefail {0} shell: bash -e -o pipefail {0}
@@ -562,9 +581,8 @@ jobs:
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Setup - name: Setup
run: | run: |
./extra/amdpci/setup_python_cap.sh ./extra/hcq/hcq_smi.py ${{ matrix.dev }} rmmod --expect
./extra/hcq/hcq_smi.py ${{ matrix.dev == 'AMD' && 'amd' || 'nv' }} rmmod ./extra/hcq/hcq_smi.py ${{ matrix.dev }} kill_pids --sudoless
./extra/hcq/hcq_smi.py ${{ matrix.dev == 'AMD' && 'amd' || 'nv' }} kill_pids
mkdir -p extra/datasets mkdir -p extra/datasets
ln -s /raid/datasets/imagenet extra/datasets/imagenet ln -s /raid/datasets/imagenet extra/datasets/imagenet
- name: setup staging db - name: setup staging db
@@ -599,6 +617,9 @@ jobs:
run: | run: |
GRAPH_ONE_KERNEL=1 NSZ=8192 python3 test/speed/external_test_copy_speed.py TestCopySpeed.testCopyDefaulttoCPUJit GRAPH_ONE_KERNEL=1 NSZ=8192 python3 test/speed/external_test_copy_speed.py TestCopySpeed.testCopyDefaulttoCPUJit
GRAPH_ONE_KERNEL=1 NSZ=8192 python3 test/speed/external_test_copy_speed.py TestCopySpeed.testCopyCPUtoDefaultJit GRAPH_ONE_KERNEL=1 NSZ=8192 python3 test/speed/external_test_copy_speed.py TestCopySpeed.testCopyCPUtoDefaultJit
- name: HEVC Decode Benchmark
if: ${{ matrix.dev == 'NV' }}
run: IGNORE_BEAM_CACHE=1 VALIDATE=1 MAX_FRAMES=100 ASSERT_FPS=1400 JITBEAM=1 PYTHONPATH=. python3 extra/hevc/decode.py
- name: Run 10 MLPerf ResNet50 training steps (1 gpu) - name: Run 10 MLPerf ResNet50 training steps (1 gpu)
if: ${{ matrix.dev == 'NV' }} if: ${{ matrix.dev == 'NV' }}
run: BENCHMARK_LOG=resnet_10steps MNISTMOCK=1 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=256 GPUS=1 MODEL=resnet python3 examples/mlperf/model_train.py run: BENCHMARK_LOG=resnet_10steps MNISTMOCK=1 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=256 GPUS=1 MODEL=resnet python3 examples/mlperf/model_train.py
@@ -621,12 +642,12 @@ jobs:
llvmspeed: llvmspeed:
name: LLVM Speed name: LLVM Speed
runs-on: [self-hosted, Linux, tinyboxrandom] runs-on: [self-hosted, Linux, tinyboxrandom]
timeout-minutes: 20 timeout-minutes: 10
if: github.repository_owner == 'tinygrad' if: github.repository_owner == 'tinygrad'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Speed Test - name: Speed Test
run: DEV=CPU:LLVM THREADS=0 python3 test/speed/external_test_speed_v_torch.py run: DEV=CPU:LLVM python3 test/speed/external_test_speed_v_torch.py
- name: Speed Test (BEAM=2) - name: Speed Test (BEAM=2)
run: BEAM=2 DEV=CPU:LLVM THREADS=0 python3 test/speed/external_test_speed_v_torch.py run: IGNORE_BEAM_CACHE=1 BEAM=2 DEV=CPU:LLVM python3 test/speed/external_test_speed_v_torch.py
+1 -1
View File
@@ -8,7 +8,7 @@ permissions:
contents: write contents: write
jobs: jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: Configure Git Credentials - name: Configure Git Credentials
+1 -33
View File
@@ -166,7 +166,7 @@ jobs:
uses: ./.github/actions/setup-tinygrad uses: ./.github/actions/setup-tinygrad
with: with:
key: windows-${{ matrix.dev }}-minimal key: windows-${{ matrix.dev }}-minimal
deps: testing_unit deps: testing_minimal
pydeps: ${{ matrix.dev == 'WEBGPU' && 'dawn-python' || '' }} pydeps: ${{ matrix.dev == 'WEBGPU' && 'dawn-python' || '' }}
- name: Set env - name: Set env
shell: bash shell: bash
@@ -179,35 +179,3 @@ jobs:
- name: Run test_tiny - name: Run test_tiny
shell: bash shell: bash
run: python -m pytest -n=auto test/test_tiny.py --durations=20 run: python -m pytest -n=auto test/test_tiny.py --durations=20
qcomclcompiletests:
name: Compile-only (QCOM CL)
runs-on: ubuntu-24.04-arm
timeout-minutes: 15
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: compile-qcomcl
deps: testing_unit
tinydreno: 'true'
- name: Set env
shell: bash
run: printf "DEV=NULL:QCOMCL:a630\nNULL_ALLOW_COPYOUT=1" >> $GITHUB_ENV
- name: Run test_ops
shell: bash
run: |
python -c "from tinygrad import Device; assert Device.DEFAULT == 'NULL'"
DEBUG=4 python3 test/backend/test_ops.py TestOps.test_add
python -m pytest -n=auto test/backend/test_ops.py --durations=20
- name: Run test_ops (IMAGE)
shell: bash
env:
IMAGE: 1
DEV: "NULL:QCOMCL:a630,IMAGE_PITCH_ALIGNMENT=64"
run: |
DEBUG=4 python test/backend/test_ops.py TestOps.test_gemm | grep read_imagef
python -m pytest -n=auto test/backend/test_ops.py --durations=20
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs: jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
+3 -3
View File
@@ -10,7 +10,7 @@ concurrency:
jobs: jobs:
checkbranch: checkbranch:
name: Check PR Branch status name: Check PR Branch status
runs-on: ubuntu-latest runs-on: ubuntu-24.04
outputs: outputs:
branchstat: ${{ steps.brstat.outputs.stat}} branchstat: ${{ steps.brstat.outputs.stat}}
steps: steps:
@@ -44,7 +44,7 @@ jobs:
permissions: permissions:
contents: read contents: read
pull-requests: write pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-24.04
needs: checkbranch needs: checkbranch
if: needs.checkbranch.outputs.branchstat == 'false' if: needs.checkbranch.outputs.branchstat == 'false'
steps: steps:
@@ -87,7 +87,7 @@ jobs:
name: Core Library Line Difference name: Core Library Line Difference
permissions: permissions:
pull-requests: write pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-24.04
needs: checkbranch needs: checkbranch
if: needs.checkbranch.outputs.branchstat == 'true' if: needs.checkbranch.outputs.branchstat == 'true'
steps: steps:
+66 -53
View File
@@ -21,7 +21,7 @@ concurrency:
jobs: jobs:
docs: docs:
name: Docs name: Docs
runs-on: &linux ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }} runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 10 timeout-minutes: 10
env: env:
CHECK_OOB: 0 CHECK_OOB: 0
@@ -31,8 +31,7 @@ jobs:
- name: Setup Environment - name: Setup Environment
uses: ./.github/actions/setup-tinygrad uses: ./.github/actions/setup-tinygrad
with: with:
deps: docs deps: "docs testing_minimal"
pydeps: "capstone torch"
- name: Build wheel and show size - name: Build wheel and show size
run: | run: |
uv build --wheel uv build --wheel
@@ -61,7 +60,7 @@ jobs:
torchbackend: torchbackend:
name: Torch Backend Tests name: Torch Backend Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -73,10 +72,7 @@ jobs:
deps: testing_unit deps: testing_unit
pydeps: "pillow torchvision expecttest" pydeps: "pillow torchvision expecttest"
llvm: 'true' llvm: 'true'
- name: Install ninja ninja: 'true'
run: |
sudo apt update || true
sudo apt install -y --no-install-recommends ninja-build
- name: Test ResNet-18 - name: Test ResNet-18
run: DEBUG=2 python3 extra/torch_backend/example.py run: DEBUG=2 python3 extra/torch_backend/example.py
- name: Test one op in torch tests - name: Test one op in torch tests
@@ -86,9 +82,26 @@ jobs:
- name: Custom tests - name: Custom tests
run: DEV=CPU:LLVM GPUS=4 TINY_BACKEND=1 python3 -m pytest -nauto extra/torch_backend/test.py extra/torch_backend/test_inplace.py extra/torch_backend/test_multigpu.py extra/torch_backend/test_kernel_fusion.py --durations=20 run: DEV=CPU:LLVM GPUS=4 TINY_BACKEND=1 python3 -m pytest -nauto extra/torch_backend/test.py extra/torch_backend/test_inplace.py extra/torch_backend/test_multigpu.py extra/torch_backend/test_kernel_fusion.py --durations=20
torchbackendtrain:
name: Torch Backend Training
runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: torch-backend-pillow-torchvision-et-pt
deps: testing_unit
llvm: 'true'
ninja: 'true'
- name: Test beautiful_mnist in torch with TINY_BACKEND
run: STEPS=20 DEV=CPU TARGET_EVAL_ACC_PCT=90.0 MAX_BUFFER_SIZE=0 TINY_BACKEND=1 python3 examples/other_mnist/beautiful_mnist_torch.py
bepython: bepython:
name: Python Backend name: Python Backend
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -126,7 +139,7 @@ jobs:
linter: linter:
name: Linters name: Linters
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
@@ -157,7 +170,7 @@ jobs:
nulltest: nulltest:
name: Null Tests name: Null Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
@@ -191,7 +204,7 @@ jobs:
unittest: unittest:
name: Unit Tests name: Unit Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
@@ -220,7 +233,7 @@ jobs:
- name: Run process replay tests - name: Run process replay tests
uses: ./.github/actions/process-replay uses: ./.github/actions/process-replay
- name: Repo line count <= 26000 lines - name: Repo line count <= 26000 lines
run: MAX_LINE_COUNT=26000 python sz.py run: MAX_LINE_COUNT=26500 python sz.py
spec: spec:
strategy: strategy:
@@ -228,7 +241,7 @@ jobs:
matrix: matrix:
group: [1, 2] group: [1, 2]
name: SPEC=2 (${{ matrix.group }}) name: SPEC=2 (${{ matrix.group }})
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -244,7 +257,7 @@ jobs:
fuzzing: fuzzing:
name: Fuzzing name: Fuzzing
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -260,7 +273,7 @@ jobs:
testopenclimage: testopenclimage:
name: CL IMAGE Tests name: CL IMAGE Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -280,7 +293,7 @@ jobs:
testopenpilot: testopenpilot:
name: openpilot Compile Tests name: openpilot Compile Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -309,7 +322,7 @@ jobs:
testonnxcpu: testonnxcpu:
name: ONNX (CPU) Tests name: ONNX (CPU) Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
@@ -328,7 +341,7 @@ jobs:
testoptim: testoptim:
name: Optimization Tests name: Optimization Tests
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -360,7 +373,7 @@ jobs:
testllm: testllm:
name: Test LLM name: Test LLM
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
env: env:
CHECK_OOB: 0 CHECK_OOB: 0
@@ -377,17 +390,17 @@ jobs:
run: | run: |
parallel --link --tagstring '[{1}]' '{2}' \ parallel --link --tagstring '[{1}]' '{2}' \
::: llama 'llama q4' qwen3.5 qwen \ ::: llama 'llama q4' qwen3.5 qwen \
::: $'echo "What\'s a male chicken called? Answer with only one word." | python3 -m tinygrad.llm --model llama3.2:1b | tee /dev/stderr | grep -i rooster' \ ::: $'echo "What\'s a male chicken called? Answer with only one word." | python3 -m tinygrad.llm --no_chat_template --model llama3.2:1b | tee /dev/stderr | grep -i rooster' \
$'echo "What\'s a male chicken called? Answer with only one word." | python3 -m tinygrad.llm --model llama3.2:1b-q4 | tee /dev/stderr | grep -i rooster' \ $'echo "What\'s a male chicken called? Answer with only one word." | python3 -m tinygrad.llm --no_chat_template --model llama3.2:1b-q4 | tee /dev/stderr | grep -i rooster' \
$'echo "What\'s a male chicken called? Answer with only one word." | python3 -m tinygrad.llm --model qwen3.5:0.8b | tee /dev/stderr | grep -i rooster' \ $'echo "What\'s a male chicken called? Answer with only one word." | python3 -m tinygrad.llm --no_chat_template --model qwen3.5:0.8b | tee /dev/stderr | grep -i rooster' \
$'echo "What\'s a female chicken called? Answer with only one word." | python3 -m tinygrad.llm --model qwen3:0.6b | tee /dev/stderr | grep -i hen' $'echo "What\'s a female chicken called? Answer with only one word." | python3 -m tinygrad.llm --no_chat_template --model qwen3:0.6b | tee /dev/stderr | grep -i hen'
# NOTE: qwen is dumb and only knows about female chickens # NOTE: qwen is dumb and only knows about female chickens
# ****** Models Tests ****** # ****** Models Tests ******
testmodels: testmodels:
name: Models name: Models
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -407,7 +420,7 @@ jobs:
testdsp: testdsp:
name: Linux (DSP) name: Linux (DSP)
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -435,7 +448,7 @@ jobs:
- 'WEBGPU' - 'WEBGPU'
name: Linux (DEV=${{ matrix.dev }}) name: Linux (DEV=${{ matrix.dev }})
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -461,7 +474,7 @@ jobs:
testamdasm: testamdasm:
name: AMD ASM IDE name: AMD ASM IDE
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 20 timeout-minutes: 20
env: env:
DEV: MOCKKFD+AMD DEV: MOCKKFD+AMD
@@ -491,7 +504,7 @@ jobs:
- name: Run AMD renderer tests (AMD:LLVM) - name: Run AMD renderer tests (AMD:LLVM)
run: DEV=MOCKKFD+AMD:LLVM python -m pytest -n=auto test/amd/ --durations 20 run: DEV=MOCKKFD+AMD:LLVM python -m pytest -n=auto test/amd/ --durations 20
- name: Run SQTT profiling tests - name: Run SQTT profiling tests
run: PROFILE=1 SQTT=1 python3 -m pytest -n=auto test/amd/test_sqtt_profiler.py run: VIZ=-2 python3 -m pytest -n=auto test/amd/test_sqtt_profiler.py
- name: Run AMD emulated tests on NULL backend - name: Run AMD emulated tests on NULL backend
env: env:
AMD: 0 AMD: 0
@@ -507,7 +520,7 @@ jobs:
hcq2: hcq2:
name: hcq2 name: hcq2
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 5 timeout-minutes: 5
steps: steps:
- name: Checkout Code - name: Checkout Code
@@ -521,16 +534,15 @@ jobs:
- name: Run HCQ2 tests - name: Run HCQ2 tests
run: HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python test/test_tiny.py run: HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python test/test_tiny.py
- name: Run HCQ2 multi-device tests - name: Run HCQ2 multi-device tests
run: | run: HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python -m pytest -n=auto test/backend/test_multitensor.py
HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python test/unit/test_multitensor.py \
TestMultiTensor.test_simple_add TestMultiTensor.test_shard_reduce \
TestMultiTensor.test_backward_sum TestMultiTensor.test_matmul_shard_0_0
- name: Run HCQ2 JIT tests - name: Run HCQ2 JIT tests
run: HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python test/unit/test_jit.py run: HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python test/unit/test_jit.py
- name: Run HCQ2 unit tests
run: HCQ_RUNTIME_DEV=PYTHON HCQ2=1 DEV=MOCKKFD+AMD FORWARD_ONLY=1 PYTHONPATH=. python -m pytest test/device/test_hcq2.py
testmockam: testmockam:
name: Linux (am) name: Linux (am)
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
env: env:
DEV: MOCKPCI+AMD DEV: MOCKPCI+AMD
@@ -566,7 +578,7 @@ jobs:
arch: [gfx1100, gfx1201, gfx950] arch: [gfx1100, gfx1201, gfx950]
name: Linux (${{ matrix.backend }} ${{ matrix.arch }}) name: Linux (${{ matrix.backend }} ${{ matrix.arch }})
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
env: env:
DEV: MOCKKFD+AMD:${{ matrix.backend == 'amdllvm' && 'LLVM' || '' }}:${{ matrix.arch }} DEV: MOCKKFD+AMD:${{ matrix.backend == 'amdllvm' && 'LLVM' || '' }}:${{ matrix.arch }}
@@ -589,7 +601,7 @@ jobs:
if: ${{ matrix.backend == 'amd' && matrix.arch == 'gfx950' }} if: ${{ matrix.backend == 'amd' && matrix.arch == 'gfx950' }}
run: PYTHONPATH=. DEV=NULL:HIP:gfx950 MXFP4=1 LLAMA_LAYERS=2 BENCHMARK=3 NULL_ALLOW_COPYOUT=1 NO_HIPCC=1 ROCM_PATH=/opt/rocm JITBEAM=0 examples/mlperf/training_submission_v6.0/tinycorp/benchmarks/llama31_8b/implementations/tinybox_8xMI350X/profile.sh run: PYTHONPATH=. DEV=NULL:HIP:gfx950 MXFP4=1 LLAMA_LAYERS=2 BENCHMARK=3 NULL_ALLOW_COPYOUT=1 NO_HIPCC=1 ROCM_PATH=/opt/rocm JITBEAM=0 examples/mlperf/training_submission_v6.0/tinycorp/benchmarks/llama31_8b/implementations/tinybox_8xMI350X/profile.sh
- name: Run pytest (amd) - name: Run pytest (amd)
run: python -m pytest -n=auto test/backend/test_ops.py test/backend/test_dtype.py test/backend/test_dtype_alu.py test/backend/test_linearizer.py test/backend/test_randomness.py test/backend/test_jit.py test/backend/test_graph.py test/backend/test_multitensor.py test/device/test_hcq.py test/external/external_test_am.py test/backend/test_asm_gemm.py::TestAsmGEMM test/opt/test_tensor_cores.py --durations=20 run: python -m pytest -n=auto test/backend/test_ops.py test/backend/test_dtype.py test/backend/test_dtype_alu.py test/backend/test_linearizer.py test/backend/test_randomness.py test/backend/test_jit.py test/backend/test_graph.py test/backend/test_multitensor.py test/device/test_hcq.py test/external/external_test_am.py test/backend/test_asm_gemm.py::TestAsmGEMM --durations=20
- name: Run disk copy tests - name: Run disk copy tests
run: python -m pytest test/unit/test_disk_tensor.py -k test_copy_from_disk run: python -m pytest test/unit/test_disk_tensor.py -k test_copy_from_disk
- name: Run TRANSCENDENTAL math - name: Run TRANSCENDENTAL math
@@ -604,7 +616,7 @@ jobs:
backend: [ptx, nv] backend: [ptx, nv]
name: Linux (${{ matrix.backend }}) name: Linux (${{ matrix.backend }})
runs-on: *linux runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 20 timeout-minutes: 20
env: env:
FORWARD_ONLY: 1 FORWARD_ONLY: 1
@@ -638,10 +650,17 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
backend: [ir3, nak] dev:
name: Compile-only (${{ matrix.backend }}) - 'NULL:IR3:a630'
runs-on: *linux - 'NULL:QCOMCL:a630'
- 'NULL:NAK:sm_120'
name: Compile-only (DEV=${{ matrix.dev }})
runs-on: ${{ github.repository == 'tinygrad/tinygrad' && github.event_name == 'pull_request' && github.event.pull_request.author_association == 'COLLABORATOR' && 'namespace-profile-tinygrad' || 'ubuntu-24.04' }}
timeout-minutes: 15 timeout-minutes: 15
env:
NULL_ALLOW_COPYOUT: 1
DEV: ${{ matrix.dev }}${{ contains(matrix.dev, 'a630') && ',IMAGE_PITCH_ALIGNMENT=64' || '' }}
IMAGE: ${{ contains(matrix.dev, 'a630') && '1' || '0' }}
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v6 uses: actions/checkout@v6
@@ -650,21 +669,15 @@ jobs:
with: with:
key: compile-${{ matrix.backend }} key: compile-${{ matrix.backend }}
deps: "testing_unit mesa" deps: "testing_unit mesa"
- name: Set env qemu: ${{ contains(matrix.dev, 'QCOMCL') }}
- name: Test IMAGE
shell: bash shell: bash
run: printf "NULL_ALLOW_COPYOUT=1\n${{ matrix.backend == 'ir3' && 'DEV=NULL:IR3:a630' || matrix.backend == 'nak' && 'DEV=NULL:NAK:sm_120' }}" >> $GITHUB_ENV if: contains(matrix.dev, 'a630')
run: DEBUG=7 python3 test/backend/test_ops.py TestOps.test_gemm | grep isam
- name: Run test_ops - name: Run test_ops
shell: bash shell: bash
run: | run: |
python -c "from tinygrad import Device; assert Device.DEFAULT == 'NULL'" python -c "from tinygrad import Device; assert Device.DEFAULT == 'NULL'"
DEBUG=4 python3 test/backend/test_ops.py TestOps.test_add DEBUG=4 python3 test/backend/test_ops.py TestOps.test_add
python -m pytest -n=auto test/backend/test_ops.py --durations=20 # QCOMCL compiles in qemu, too slow for parallel workers
- name: Run test_ops (IMAGE) ${{ contains(matrix.dev, 'QCOMCL') && 'PARALLEL=0' || '' }} python -m pytest -n=auto test/backend/test_ops.py --durations=20
if: matrix.backend == 'ir3'
shell: bash
env:
IMAGE: 1
DEV: "NULL:IR3:a630,IMAGE_PITCH_ALIGNMENT=64"
run: |
DEBUG=4 python3 test/backend/test_ops.py TestOps.test_gemm | grep image_load
python -m pytest -n=auto test/backend/test_ops.py --durations=20
+1
View File
@@ -69,3 +69,4 @@ mutants
dagre/ dagre/
graphlib/ graphlib/
uv.lock uv.lock
pi_session_window0.jsonl
+1 -1
View File
@@ -28,7 +28,7 @@ repos:
pass_filenames: false pass_filenames: false
- id: tests - id: tests
name: comprehensive test suite name: comprehensive test suite
entry: env OMP_NUM_THREADS=1 SKIP_SLOW_TEST=1 PYTHONPATH="." python3 -m pytest -n=6 test/backend/test_ops.py test/backend/test_schedule.py test/unit/test_assign.py test/backend/test_tensor.py test/backend/test_jit.py test/unit/test_schedule_cache.py test/null/test_pattern_matcher.py test/null/test_uop_symbolic.py test/unit/test_helpers.py entry: env OMP_NUM_THREADS=1 SKIP_SLOW_TEST=1 PYTHONPATH="." python3 -m pytest -n=6 test/backend/test_ops.py test/backend/test_schedule.py test/backend/test_assign.py test/backend/test_tensor.py test/backend/test_jit.py test/unit/test_schedule_cache.py test/null/test_pattern_matcher.py test/null/test_uop_symbolic.py test/unit/test_helpers.py
language: system language: system
always_run: true always_run: true
pass_filenames: false pass_filenames: false
+1
View File
@@ -4,3 +4,4 @@
- Run `python -m mypy tinygrad/` to typecheck - Run `python -m mypy tinygrad/` to typecheck
- Run `python -m ruff check .` to lint - Run `python -m ruff check .` to lint
- Read `./tinygrad/viz/README.md` for profiling and debugging rewrite rules - Read `./tinygrad/viz/README.md` for profiling and debugging rewrite rules
- Do not do amend commits. Always do a new commit if a force push to origin would be required.
+1 -1
View File
@@ -140,7 +140,7 @@ Documentation along with a quick start guide can be found on the [docs website](
```python ```python
from tinygrad import Tensor from tinygrad import Tensor
x = Tensor.eye(3) x = Tensor.eye(3).clone() # clone to make it a buffer
y = Tensor([[2.0,0,-2.0]]) y = Tensor([[2.0,0,-2.0]])
z = y.matmul(x).sum() z = y.matmul(x).sum()
z.backward() z.backward()
+1 -1
View File
@@ -1 +1 @@
8611fe22a7fcc7d1928bbde19ded66277cb12f3e f6fc4e3f2c3db5fae1e19cbfbc3ad9fc579a12ae
+1 -1
View File
@@ -2,7 +2,7 @@ import os, pytest, signal, threading
@pytest.hookimpl(wrapper=True) @pytest.hookimpl(wrapper=True)
def pytest_runtest_call(item): def pytest_runtest_call(item):
t = threading.Timer(int(os.getenv("TEST_TIMEOUT", 300)), os.kill, args=(os.getpid(), signal.SIGABRT)) t = threading.Timer(int(os.getenv("TEST_TIMEOUT", 90)), os.kill, args=(os.getpid(), signal.SIGABRT))
t.start() t.start()
try: yield try: yield
finally: finally:
+1 -1
View File
@@ -122,7 +122,7 @@ def example_5_custom_assembly(a:Tensor, correct):
offset_dwords = (self.labels[inst._target] - inst._pos - inst.size()) // 4 offset_dwords = (self.labels[inst._target] - inst._pos - inst.size()) // 4
if not -32768 <= offset_dwords <= 32767: raise ValueError(f"branch to '{inst._target}' offset {offset_dwords} exceeds simm16 range") if not -32768 <= offset_dwords <= 32767: raise ValueError(f"branch to '{inst._target}' offset {offset_dwords} exceeds simm16 range")
inst.simm16 = offset_dwords inst.simm16 = offset_dwords
return UOp(Ops.PROGRAM, src=(sink, UOp(Ops.LINEAR, src=tuple([UOp(Ops.INS, arg=x) for x in self.instructions])))) return UOp(Ops.PROGRAM, src=(sink, UOp(Ops.LINEAR, src=tuple([UOp(Ops.INS, arg=(x, dtypes.void)) for x in self.instructions]))))
CU_COUNT = 32 CU_COUNT = 32
LANES = 64 LANES = 64
+1 -1
View File
@@ -52,7 +52,7 @@ In `kernel.py` we have a set of `OptOps`, these control the parameters of the sp
The main bottleneck in most kernels is accessing memory. In a freshman algorithms class, you'll learn about cache aware matrix multiplication, and this is all forms of that. While the same math is run, the order in which you run it can have large impacts on the speed depending on if the data you are loading. OptOps will change this order. The main bottleneck in most kernels is accessing memory. In a freshman algorithms class, you'll learn about cache aware matrix multiplication, and this is all forms of that. While the same math is run, the order in which you run it can have large impacts on the speed depending on if the data you are loading. OptOps will change this order.
Memory, even cache, is often much slower than accessing the register file. The amount of times data is used in math is called the "arithmetic intensity". For operations like BS=1 GEMV, the arithmetic intensity is 1, but for GEMMs and convs it can be much higher. OptOps like UPCAST and UNROLL can increase this, but be careful of making them too large, as if there's too much register pressure on the GPU the warp scheduler may not be able to fit many warps, or even worse, it could be spilling to local memory. Memory, even cache, is often much slower than accessing the register file. The amount of times data is used in math is called the "arithmetic intensity". For operations like BS=1 GEMV, the arithmetic intensity is 1, but for GEMMs and convs it can be much higher. Splitting an axis into UPCAST can increase this, but be careful of making them too large, as if there's too much register pressure on the GPU the warp scheduler may not be able to fit many warps, or even worse, it could be spilling to local memory.
4090s have 1 TB/s of ram bandwidth and ~160 TFLOPS of compute, so you need to use each loaded value ~100 times. The L1 cache has around 40 TB/s of bandwidth, so in order to get full compute utilization you need to use each value ~4 times. 4090s have 1 TB/s of ram bandwidth and ~160 TFLOPS of compute, so you need to use each loaded value ~100 times. The L1 cache has around 40 TB/s of bandwidth, so in order to get full compute utilization you need to use each value ~4 times.
+5 -5
View File
@@ -5,7 +5,7 @@ from multiprocessing import Queue, Process, shared_memory, connection, Lock
import numpy as np import numpy as np
from tinygrad import dtypes, Tensor from tinygrad import dtypes, Tensor
from tinygrad.helpers import getenv, prod, Context, round_up, tqdm, OSX, NUM_CPU_THREADS from tinygrad.helpers import getenv, prod, Context, round_up, tqdm, OSX, CPU_COUNT
from tinygrad.nn.state import TensorIO from tinygrad.nn.state import TensorIO
### ResNet ### ResNet
@@ -131,7 +131,7 @@ def batch_load_resnet(batch_size=64, val=False, shuffle=True, seed=None, pad_fir
else: X = Tensor.empty(*sz, dtype=dtypes.uint8, device=f"disk:/dev/shm/{shm_name}") else: X = Tensor.empty(*sz, dtype=dtypes.uint8, device=f"disk:/dev/shm/{shm_name}")
Y = [None] * (batch_size*BATCH_COUNT) Y = [None] * (batch_size*BATCH_COUNT)
for _ in range(NUM_CPU_THREADS.value): for _ in range(CPU_COUNT):
p = Process(target=loader_process, args=(q_in, q_out, X, seed)) p = Process(target=loader_process, args=(q_in, q_out, X, seed))
p.daemon = True p.daemon = True
p.start() p.start()
@@ -212,7 +212,7 @@ def batch_load_train_bert(BS:int, seed:int|None=None):
rng.shuffle(fs) rng.shuffle(fs)
train_files.append(fs.pop(0)) train_files.append(fs.pop(0))
cycle_length = min(NUM_CPU_THREADS.value, len(train_files)) cycle_length = min(CPU_COUNT, len(train_files))
assert cycle_length > 0, "cycle_length must be greater than 0" assert cycle_length > 0, "cycle_length must be greater than 0"
dataset = InterleavedDataset(train_files, cycle_length) dataset = InterleavedDataset(train_files, cycle_length)
@@ -301,7 +301,7 @@ def batch_load_unet3d(preprocessed_dataset_dir:Path, batch_size:int=6, val:bool=
X = Tensor.empty(*sz, dtype=dtypes.float32, device=f"disk:/dev/shm/{shm_name_x}") X = Tensor.empty(*sz, dtype=dtypes.float32, device=f"disk:/dev/shm/{shm_name_x}")
Y = Tensor.empty(*sz, dtype=dtypes.uint8, device=f"disk:/dev/shm/{shm_name_y}") Y = Tensor.empty(*sz, dtype=dtypes.uint8, device=f"disk:/dev/shm/{shm_name_y}")
for _ in range(NUM_CPU_THREADS.value): for _ in range(CPU_COUNT):
proc = Process(target=load_unet3d_data, args=(preprocessed_dataset_dir, seed, queue_in, queue_out, X, Y)) proc = Process(target=load_unet3d_data, args=(preprocessed_dataset_dir, seed, queue_in, queue_out, X, Y))
proc.daemon = True proc.daemon = True
proc.start() proc.start()
@@ -437,7 +437,7 @@ def batch_load_retinanet(dataset, val:bool, base_dir:Path, batch_size:int=32, sh
dataset_iter = iter(image_ids) dataset_iter = iter(image_ids)
try: try:
for _ in range(NUM_CPU_THREADS.value): for _ in range(CPU_COUNT):
proc = Process( proc = Process(
target=load_retinanet_data, target=load_retinanet_data,
args=(base_dir, val, queue_in, queue_out, imgs, boxes, labels), args=(base_dir, val, queue_in, queue_out, imgs, boxes, labels),
+30 -42
View File
@@ -1667,15 +1667,14 @@ def train_llama3():
def train_gptoss(): def train_gptoss():
from examples.mlperf.models.gpt_oss import GPTOSS, GPT_OSS_20B, apply_grad, FP8_DTYPE from examples.mlperf.models.gpt_oss import GPTOSS, GPT_OSS_20B, apply_grad, FP8_DTYPE
from examples.mlperf.lr_schedulers import CosineAnnealingLRWithWarmup from examples.mlperf.lr_schedulers import CosineAnnealingLRWithWarmup
from examples.mlperf.optim import GradAccClipAdamW, GradAccClipAdamWGroup, clip_grads from examples.mlperf.optim import GradAccClipAdamW, GradAccClipAdamWGroup, fclip_grads
BENCHMARK = getenv("BENCHMARK") BENCHMARK = getenv("BENCHMARK")
config = {} config = {}
BASEDIR = config["BASEDIR"] = Path(getenv("BASEDIR", "/raid/datasets/c4-8b/")) BASEDIR = config["BASEDIR"] = Path(getenv("BASEDIR", "/raid/datasets/c4-8b/"))
BS = config["BS"] = getenv("BS", 16) BS = config["BS"] = getenv("BS", 16)
grad_acc = config["GRADIENT_ACC_STEPS"] = getenv("GRADIENT_ACC_STEPS", 1) GBS = config["GLOBAL_BATCH_SIZE"] = BS
GBS = config["GLOBAL_BATCH_SIZE"] = BS * grad_acc
SEED = config["SEED"] = getenv("SEED", 5760) SEED = config["SEED"] = getenv("SEED", 5760)
DATA_SEED = config["DATA_SEED"] = getenv("DATA_SEED", SEED) DATA_SEED = config["DATA_SEED"] = getenv("DATA_SEED", SEED)
SEQLEN = config["SEQLEN"] = getenv("SEQLEN", 8192) SEQLEN = config["SEQLEN"] = getenv("SEQLEN", 8192)
@@ -1737,13 +1736,13 @@ def train_gptoss():
params_wd = [p for p in params if p.ndim >= 3] params_wd = [p for p in params if p.ndim >= 3]
params_no_wd = [p for p in params if p.ndim < 3] params_no_wd = [p for p in params if p.ndim < 3]
optim = GradAccClipAdamWGroup( optim = GradAccClipAdamWGroup(
GradAccClipAdamW(params_wd, lr=0.0, b1=opt_adamw_beta_1, b2=opt_adamw_beta_2, eps=opt_adamw_epsilon, weight_decay=opt_adamw_weight_decay, grad_acc=grad_acc, device=optim_device), GradAccClipAdamW(params_wd, lr=0.0, b1=opt_adamw_beta_1, b2=opt_adamw_beta_2, eps=opt_adamw_epsilon, weight_decay=opt_adamw_weight_decay, grad_acc=1, device=optim_device),
GradAccClipAdamW(params_no_wd, lr=0.0, b1=opt_adamw_beta_1, b2=opt_adamw_beta_2, eps=opt_adamw_epsilon, weight_decay=0.0, grad_acc=grad_acc, device=optim_device), GradAccClipAdamW(params_no_wd, lr=0.0, b1=opt_adamw_beta_1, b2=opt_adamw_beta_2, eps=opt_adamw_epsilon, weight_decay=0.0, grad_acc=1, device=optim_device),
) )
for p in optim.params: for p in optim.params:
grad_dtype = dtypes.bfloat16 if p.dtype == FP8_DTYPE else p.dtype p.grad = p.zeros_like(dtype=dtypes.bfloat16 if p.dtype == FP8_DTYPE else p.dtype).contiguous()
p.grad = p.zeros_like(dtype=grad_dtype).contiguous() if getattr(p, "_zero2", False): p.grad = optim.optimizers[0]._zero_shard(p.grad)
grads = [p.grad for p in optim.params] grads = [p.grad for p in optim.params]
from extra.gemm.cdna_asm_gemm import _mx_block_scale from extra.gemm.cdna_asm_gemm import _mx_block_scale
@@ -1770,31 +1769,32 @@ def train_gptoss():
@TinyJit @TinyJit
@Context(TRAINING=1) @Context(TRAINING=1)
def minibatch(tokens:Tensor): def step(tokens:Tensor):
if is_dp: tokens = tokens.to(None).shard(device, 0) if is_dp: tokens = tokens.to(None).shard(device, 0)
if not is_sharding: tokens = tokens.to(None) if not is_sharding: tokens = tokens.to(None)
logits:Tensor = model(tokens[:, :-1], save=True) logits:Tensor = model(tokens[:, :-1], save=True)
loss = logits.sparse_categorical_crossentropy(tokens[:, 1:]) if getenv("FUSED_CE", 0):
from extra.llama_kernels.fused_ce import fused_ce_loss
loss = fused_ce_loss(logits.cast(dtypes.bfloat16), tokens[:, 1:], label_smoothing=0.0)
else:
loss = logits.sparse_categorical_crossentropy(tokens[:, 1:])
for g, new_g in zip(grads, loss.gradient(*optim.params)): for g, new_g in zip(grads, loss.gradient(*optim.params)):
apply_grad(g, new_g.uop) apply_grad(g, new_g.uop)
loss_cpu = loss.flatten().float().to("CPU") Tensor.realize(loss, *grads)
return loss_cpu.realize(*grads)
@TinyJit clipped_grads, grad_norm = fclip_grads(grads, 1.0)
def optim_step(): optim.fstep(clipped_grads, grad_norm)
grad_norm = clip_grads(grads, grad_acc, 1.0)
optim.fstep(grads, grad_norm)
scheduler.step() scheduler.step()
for g in grads: g.assign(0) loss_cpu = loss.flatten().float().to("CPU")
lr_cpu = optim.lr.float().to("CPU") lr_cpu = optim.lr.float().to("CPU")
grad_norm_cpu = grad_norm.float().to("CPU") grad_norm_cpu = grad_norm.float().to("CPU")
Tensor.realize(lr_cpu, grad_norm_cpu, *grads, *fp8_inv_scales) Tensor.realize(loss_cpu, lr_cpu, grad_norm_cpu, *grads, *fp8_inv_scales)
return lr_cpu, grad_norm_cpu return loss_cpu, lr_cpu, grad_norm_cpu
@TinyJit @TinyJit
@Context(TRAINING=0) @Context(TRAINING=0)
@@ -1843,30 +1843,20 @@ def train_gptoss():
profile_marker(f"train @ {i}") profile_marker(f"train @ {i}")
st = time.perf_counter() st = time.perf_counter()
stopped = False ist = time.perf_counter()
losses, data_time, dev_time = [], 0, 0
for _ in range(grad_acc if i >= 2 else 1):
ist = time.perf_counter()
try: tokens = next(train_iter)
except StopIteration:
stopped = True
break
mst = time.perf_counter()
data_time += mst - ist
losses.append(minibatch(tokens).item())
dev_time += time.perf_counter() - mst
if stopped: break
gt = time.perf_counter() try: tokens = next(train_iter)
ret = optim_step() except StopIteration: break
lr, grad_norm = ret[0].item(), ret[1].item() mst = time.perf_counter()
data_time = mst - ist
ret = step(tokens)
dev_time = time.perf_counter() - mst
loss, lr, grad_norm = ret[0].item(), ret[1].item(), ret[2].item()
et = time.perf_counter() et = time.perf_counter()
loss = sum(losses) / len(losses)
optim_time = et - gt
dev_time += optim_time
step_time = et - st step_time = et - st
gbs_time = gt - st
if BENCHMARK: step_times.append(step_time) if BENCHMARK: step_times.append(step_time)
i += 1 i += 1
@@ -1876,7 +1866,7 @@ def train_gptoss():
gflops = GlobalCounters.global_ops / 1e9 / dev_time gflops = GlobalCounters.global_ops / 1e9 / dev_time
mfu = ((6 * num_params * SEQLEN * GBS) / (dev_time * device_count * 4.6e15)) * 100 mfu = ((6 * num_params * SEQLEN * GBS) / (dev_time * device_count * 4.6e15)) * 100
tqdm.write( tqdm.write(
f"{i:5} {step_time:.3f} s step, {gbs_time:.3f} s gbs, {optim_time:.3f} s optim, {data_time:.3f} s data, {loss:.4f} loss, " \ f"{i:5} {step_time:.3f} s step, {dev_time:.3f} s dev, {data_time:.3f} s data, {loss:.4f} loss, " \
f"{lr:.12f} LR, {grad_norm:.6f} grad_norm, {mem_gb:.2f} GB used, {gflops:9.2f} GFLOPS, {mfu:5.2f}% MFU") f"{lr:.12f} LR, {grad_norm:.6f} grad_norm, {mem_gb:.2f} GB used, {gflops:9.2f} GFLOPS, {mfu:5.2f}% MFU")
if DEBUG >= 1: tqdm.write(" mem per device: " + ', '.join(f"{dev}: {mem/1e9:.2f} GB" for dev, mem in sorted(GlobalCounters.mem_used_per_device.items()))) if DEBUG >= 1: tqdm.write(" mem per device: " + ', '.join(f"{dev}: {mem/1e9:.2f} GB" for dev, mem in sorted(GlobalCounters.mem_used_per_device.items())))
@@ -1886,8 +1876,6 @@ def train_gptoss():
"train/lr": lr, "train/lr": lr,
"train/grad_norm": grad_norm, "train/grad_norm": grad_norm,
"train/step_time": step_time, "train/step_time": step_time,
"train/gbs_time": gbs_time,
"train/optim_time": optim_time,
"train/dev_time": dev_time, "train/dev_time": dev_time,
"train/data_time": data_time, "train/data_time": data_time,
"train/mem": mem_gb, "train/mem": mem_gb,
+55 -15
View File
@@ -12,7 +12,7 @@ from tinygrad.helpers import Timing, colored, GlobalCounters, profile_marker
from tinygrad.uop.ops import Ops, UOp from tinygrad.uop.ops import Ops, UOp
from extra.models.llama import apply_rotary_emb from extra.models.llama import apply_rotary_emb
from extra.llama_kernels.rmsnorm import rmsnorm from extra.llama_kernels.rmsnorm import rmsnorm
from extra.gemm.cdna_asm_gemm import _mx_block_scale, _mx_block_scale_3d, quantize_mxfp8 from extra.gemm.cdna_asm_gemm import _mx_block_scale, _mx_block_scale_3d, quantize_mxfp8, asm_gemm, can_use_asm_gemm
from extra.gemm.moe_gemm import grouped_mx_gemm from extra.gemm.moe_gemm import grouped_mx_gemm
from extra.gemm.moe_routing import route, dispatch, combine from extra.gemm.moe_routing import route, dispatch, combine
@@ -61,7 +61,25 @@ def dequant_weight(w_q:Tensor, w_scale:Tensor) -> Tensor:
call = UOp.maketuple(fxn.uop).call(w_q.uop, w_scale.uop, grad_fxn=_dequant_bwd) call = UOp.maketuple(fxn.uop).call(w_q.uop, w_scale.uop, grad_fxn=_dequant_bwd)
return Tensor(call.gettuple(0)) return Tensor(call.gettuple(0))
def matmul_mx(x:Tensor, w_q:Tensor, w_scale:Tensor) -> Tensor: def matmul_mx(x:Tensor|tuple[Tensor, Tensor], w_q:Tensor, w_scale:Tensor) -> Tensor:
if isinstance(x, tuple):
assert ASM_GEMM, "pre-quantized MXFP8 input requires ASM_GEMM"
from extra.gemm.cdna_asm_gemm import asm_gemm, can_use_asm_gemm, mx_pack
x_q, x_e8 = x
l_shape, padded = x_q.shape[:-1], x_q.shape[-1]
x_q, x_e8 = x_q.reshape(-1, padded), x_e8.reshape(-1, padded // 32)
K, N = w_q.shape[1], w_q.shape[0]
assert padded >= K and (padded - K) % 32 == 0 and x_e8.shape[-1] == padded // 32
wq, ws = w_q, w_scale
if (pad := padded - K):
wq = wq.pad(((0, 0), (0, pad)))
ws = ws.pad(((0, 0), (0, pad // 32)), value=127).cast(dtypes.uint8)
if (npad := (-N) % 256):
wq = wq.pad(((0, npad), (0, 0)))
ws = ws.pad(((0, npad), (0, 0)), value=127).cast(dtypes.uint8)
assert can_use_asm_gemm(x_q, wq.T)
out = asm_gemm(x_q, wq.T, mx=True, mx_scales=(mx_pack(x_e8), x_e8, mx_pack(ws), ws), mx_w_stored=True)
return (out[:, :N] if npad else out).reshape(*l_shape, N).cast(dtypes.bfloat16)
l_shape = x.shape[:-1] l_shape = x.shape[:-1]
if ASM_GEMM: if ASM_GEMM:
from extra.gemm.cdna_asm_gemm import asm_gemm, can_use_asm_gemm, mx_pack from extra.gemm.cdna_asm_gemm import asm_gemm, can_use_asm_gemm, mx_pack
@@ -146,6 +164,7 @@ class GPTOSS:
return w_q, w_e8.is_param_(False) return w_q, w_e8.is_param_(False)
if moe: if moe:
qs = [_one(*shape[1:]) for _ in range(shape[0])] qs = [_one(*shape[1:]) for _ in range(shape[0])]
for q in qs: q[0]._zero2 = True # grad arrives sharded on the expert axis under ZeRO-2 (moe_gemm)
return [q[0] for q in qs], [q[1] for q in qs] return [q[0] for q in qs], [q[1] for q in qs]
return _one(*shape) return _one(*shape)
@@ -174,20 +193,30 @@ class GPTOSS:
def attention(self, x:Tensor, freqs_cis:Tensor, mask:Tensor, sliding:bool, *, attention_norm:Tensor, wqkv:Tensor, def attention(self, x:Tensor, freqs_cis:Tensor, mask:Tensor, sliding:bool, *, attention_norm:Tensor, wqkv:Tensor,
wqkv_scale:Tensor, wqkv_bias:Tensor, wo:Tensor, wo_scale:Tensor, wo_bias:Tensor, sinks:Tensor): wqkv_scale:Tensor, wqkv_bias:Tensor, wo:Tensor, wo_scale:Tensor, wo_bias:Tensor, sinks:Tensor):
bsz, seqlen, _ = x.shape bsz, seqlen, _ = x.shape
x_normed, rrms = rmsnorm(x, self.norm_eps)
qkv = matmul_mx(x_normed * attention_norm, wqkv, wqkv_scale) + wqkv_bias if getenv("FUSED_RMSNORM_MUL", 0):
from extra.gptoss_kernels.rmsnorm import rmsnorm_mul
x_normed, rrms = rmsnorm_mul(x, attention_norm, self.norm_eps)
norm_saves = [x_normed, rrms]
else:
x_normed, rrms = rmsnorm(x, self.norm_eps)
qkv = matmul_mx(x_normed * attention_norm, wqkv, wqkv_scale) + wqkv_bias
norm_saves = [x_normed, rrms]
qkv = qkv.reshape(bsz, seqlen, self.n_kv_heads, self.n_rep + 2, self.head_dim) qkv = qkv.reshape(bsz, seqlen, self.n_kv_heads, self.n_rep + 2, self.head_dim)
xq = qkv[:, :, :, :self.n_rep].reshape(bsz, seqlen, self.n_heads, self.head_dim) xq = qkv[:, :, :, :self.n_rep].reshape(bsz, seqlen, self.n_heads, self.head_dim)
xk, xv = qkv[:, :, :, self.n_rep], qkv[:, :, :, self.n_rep + 1] xk, xv = qkv[:, :, :, self.n_rep], qkv[:, :, :, self.n_rep + 1]
xq, xk = apply_rotary_emb(xq, xk, freqs_cis) xq, xk = apply_rotary_emb(xq, xk, freqs_cis)
xq, xk, xv = xq.cast(dtypes.bfloat16), xk.cast(dtypes.bfloat16), xv.cast(dtypes.bfloat16) # (B,N,H,D)/(B,N,KV,D) xq, xk, xv = xq.cast(dtypes.bfloat16), xk.cast(dtypes.bfloat16), xv.cast(dtypes.bfloat16) # (B,N,H,D)/(B,N,KV,D)
if sliding: fa_saves = []
attn = self._sliding_attention(xq, xk, xv, sinks) if getenv("HK_FLASH_ATTENTION"):
elif getenv("HK_FLASH_ATTENTION"):
from extra.thunder.amd.fa import flash_attention from extra.thunder.amd.fa import flash_attention
attn, *_ = flash_attention(xq, xk, xv, is_causal=True, write_flat=True, sinks=sinks) attn, _, l_vec = flash_attention(xq, xk, xv, is_causal=True, write_flat=True, sinks=sinks, window=self.sliding_window if sliding else 0)
attn = attn.reshape(bsz, seqlen, self.n_heads * self.head_dim) attn = attn.reshape(bsz, seqlen, self.n_heads * self.head_dim)
fa_saves = [xq, xk, xv, l_vec]
elif sliding:
attn = self._sliding_attention(xq, xk, xv, sinks)
else: else:
xqm = xq.reshape(bsz, seqlen, self.n_kv_heads, self.n_rep, self.head_dim).permute(0, 2, 3, 1, 4) xqm = xq.reshape(bsz, seqlen, self.n_kv_heads, self.n_rep, self.head_dim).permute(0, 2, 3, 1, 4)
xkm, xvm = xk.permute(0, 2, 1, 3).unsqueeze(2), xv.permute(0, 2, 1, 3).unsqueeze(2) xkm, xvm = xk.permute(0, 2, 1, 3).unsqueeze(2), xv.permute(0, 2, 1, 3).unsqueeze(2)
@@ -199,13 +228,19 @@ class GPTOSS:
attn = (w @ xvm).permute(0, 3, 1, 2, 4).reshape(bsz, seqlen, self.n_heads * self.head_dim) attn = (w @ xvm).permute(0, 3, 1, 2, 4).reshape(bsz, seqlen, self.n_heads * self.head_dim)
out = matmul_mx(attn, wo, wo_scale) + wo_bias out = matmul_mx(attn, wo, wo_scale) + wo_bias
return out, [x_normed, rrms, attn] return out, [attn] + norm_saves + fa_saves
def feed_forward(self, x:Tensor, *, ffn_norm:Tensor, gate:Tensor, gate_bias:Tensor, def feed_forward(self, x:Tensor, *, ffn_norm:Tensor, gate:Tensor, gate_bias:Tensor,
w_gate_up:Tensor, w_gate_up_scale:Tensor, w_gate_up_bias:Tensor, w_gate_up:Tensor, w_gate_up_scale:Tensor, w_gate_up_bias:Tensor,
w_down:Tensor, w_down_scale:Tensor, w_down_bias:Tensor): w_down:Tensor, w_down_scale:Tensor, w_down_bias:Tensor):
x_normed, rrms = rmsnorm(x, self.norm_eps) if getenv("FUSED_RMSNORM_MUL", 0):
inp = x_normed * ffn_norm from extra.gptoss_kernels.rmsnorm import rmsnorm_mul
x_normed, rrms = rmsnorm_mul(x, ffn_norm, self.norm_eps)
inp = x_normed
else:
x_normed, rrms = rmsnorm(x, self.norm_eps)
inp = x_normed * ffn_norm
logits = inp.float() @ gate.float().T + gate_bias.float() logits = inp.float() @ gate.float().T + gate_bias.float()
dim, inter = self.dim, self.intermediate_size dim, inter = self.dim, self.intermediate_size
@@ -220,6 +255,7 @@ class GPTOSS:
z = grouped_mx_gemm(_pad_cols(y.cast(dtypes.bfloat16)), (w_down, w_down_scale), r.off)[:, :dim] \ z = grouped_mx_gemm(_pad_cols(y.cast(dtypes.bfloat16)), (w_down, w_down_scale), r.off)[:, :dim] \
+ (onehot @ w_down_bias.float()).cast(dtypes.bfloat16) + (onehot @ w_down_bias.float()).cast(dtypes.bfloat16)
out = combine(z, r, inp.shape[0], self.experts_per_tok).reshape(bsz, seqlen, dim) out = combine(z, r, inp.shape[0], self.experts_per_tok).reshape(bsz, seqlen, dim)
return out, [x_normed, rrms, xg, h, y, z, r.weights, r.dest_row, r.off]
else: else:
thresh = logits.topk(self.experts_per_tok)[0][..., -1:] thresh = logits.topk(self.experts_per_tok)[0][..., -1:]
weights = (logits >= thresh).where(logits, -float("inf")).softmax(-1) weights = (logits >= thresh).where(logits, -float("inf")).softmax(-1)
@@ -263,7 +299,11 @@ class GPTOSS:
w_down=self.w_down[i], w_down_scale=self.w_down_scale[i], w_down_bias=self.w_down_bias[i]) w_down=self.w_down[i], w_down_scale=self.w_down_scale[i], w_down_bias=self.w_down_bias[i])
h, *_ = self.run_layer(h, freqs_cis, mask_full, i % 2 == 0, attn_kwargs, ffn_kwargs, save=save) h, *_ = self.run_layer(h, freqs_cis, mask_full, i % 2 == 0, attn_kwargs, ffn_kwargs, save=save)
logits = self.norm(h) @ self.output.T h_normed = self.norm(h)
pad = (-self.dim) % 256
h_padded, w_padded = h_normed.pad((None, None, (0, pad))), self.output.pad(((0, 0), (0, pad)))
if ASM_GEMM and can_use_asm_gemm(h_padded, w_padded.T): logits = asm_gemm(h_padded, w_padded.T)
else: logits = h_normed @ self.output.T
return logits return logits
def _get_pads(uop:UOp) -> list[UOp]: def _get_pads(uop:UOp) -> list[UOp]:
@@ -274,14 +314,14 @@ def apply_grad(grad_buf:Tensor, new_grad:UOp):
pads = _get_pads(new_grad) pads = _get_pads(new_grad)
if len(pads) <= 1: if len(pads) <= 1:
new_grad = new_grad.cast(grad_buf.dtype) new_grad = new_grad.cast(grad_buf.dtype)
grad_buf.uop = grad_buf.uop.after(grad_buf.uop.store(grad_buf.uop + new_grad)) grad_buf.uop = grad_buf.uop.after(grad_buf.uop.store(new_grad))
return return
cur = grad_buf.uop cur = grad_buf.uop
for pad in sorted(pads, key=lambda p: p.marg[0][0] if p.op == Ops.PAD else 0, reverse=True): for pad in sorted(pads, key=lambda p: p.marg[0][0] if p.op == Ops.PAD else 0, reverse=True):
if pad.op == Ops.PAD: if pad.op == Ops.PAD:
grad_shrink = tuple([(p[0], s+p[0]) for s,p in zip(pad.src[0].shape, pad.marg)]) grad_shrink = tuple((p[0], s+p[0]) for s,p in zip(pad.src[0].shape, pad.marg))
buf_slice = cur.shrink(grad_shrink) buf_slice = cur.shrink(grad_shrink)
cur = cur.after(buf_slice.store(buf_slice + pad.src[0].cast(cur.dtype))) cur = cur.after(buf_slice.store(pad.src[0].cast(cur.dtype)))
else: else:
cur = cur.after(cur.store(cur + pad.cast(cur.dtype))) cur = cur.after(cur.store(cur + pad.cast(cur.dtype)))
grad_buf.uop = cur grad_buf.uop = cur
+6 -1
View File
@@ -15,7 +15,7 @@ def stochastic_round_bf16(x:Tensor) -> Tensor:
bits = x.bitcast(dtypes.uint32) bits = x.bitcast(dtypes.uint32)
if isinstance(x.device, tuple): if isinstance(x.device, tuple):
shape = x.uop.shard_shape if x.uop.axis is not None else x.shape shape = x.uop.shard_shape if x.uop.axis is not None else x.shape
noise = Tensor(UOp(Ops.MSTACK, dtypes.default_float, tuple(Tensor.rand(*shape, device=d).uop for d in x.device))) noise = Tensor(UOp(Ops.MSTACK, src=tuple(Tensor.rand(*shape, device=d).uop for d in x.device)))
else: else:
noise = x.rand_like() noise = x.rand_like()
noise = (noise * 0xFFFF).cast(dtypes.uint32) noise = (noise * 0xFFFF).cast(dtypes.uint32)
@@ -27,6 +27,11 @@ def clip_grads(grads:list[Tensor], grad_acc, clip_norm) -> Tensor:
for g in grads: g.assign((g * (clip_norm / (total_norm + 1e-6)).clamp(max_=1.0)).cast(g.dtype)) for g in grads: g.assign((g * (clip_norm / (total_norm + 1e-6)).clamp(max_=1.0)).cast(g.dtype))
return total_norm return total_norm
def fclip_grads(grads:list[Tensor], clip_norm) -> Tensor:
total_norm = Tensor.stack(*[g.float().square().sum() for g in grads]).sum().sqrt().contiguous()
scale = (clip_norm / (total_norm + 1e-6)).clamp(max_=1.0)
return [(g * scale).cast(g.dtype) for g in grads], total_norm
class GradAccClipAdamW(Optimizer): class GradAccClipAdamW(Optimizer):
def __init__(self, params:list[Tensor], lr=0.001, b1=0.9, b2=0.999, eps=1e-6, weight_decay=0.0, grad_acc=1, clip_norm=1.0, device=None, fused=FUSE_OPTIM): def __init__(self, params:list[Tensor], lr=0.001, b1=0.9, b2=0.999, eps=1e-6, weight_decay=0.0, grad_acc=1, clip_norm=1.0, device=None, fused=FUSE_OPTIM):
super().__init__(params, lr, device, fused) super().__init__(params, lr, device, fused)
@@ -0,0 +1,13 @@
from pathlib import Path
from examples.mlperf.dataloader import get_llama3_dataset
from tinygrad.helpers import getenv
BASEDIR = Path(getenv("BASEDIR", "/raid/datasets/c4-8b/"))
SAMPLES = getenv("SAMPLES", 1_200_000 * 32)
EVAL_SAMPLES = getenv("EVAL_SAMPLES", 1024)
SEQLEN = getenv("SEQLEN", 8192)
DATA_SEED = getenv("DATA_SEED", 5760)
get_llama3_dataset(SAMPLES, SEQLEN, BASEDIR, seed=DATA_SEED, val=False, small=True)
get_llama3_dataset(EVAL_SAMPLES, SEQLEN, BASEDIR, seed=0, val=True, small=True)
@@ -26,7 +26,7 @@ export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
export SPLIT_W13=${SPLIT_W13:-0} export SPLIT_W13=${SPLIT_W13:-0}
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-0} export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-0}
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16" export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="float32"
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2} export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
export GBS=$((BS * GRADIENT_ACC_STEPS)) export GBS=$((BS * GRADIENT_ACC_STEPS))
@@ -35,7 +35,7 @@ export BASEDIR="/raid/datasets/c4-8b/"
export SMALL=1 export SMALL=1
export LLAMA3_SIZE=${LLAMA3_SIZE:-"8B"} export LLAMA3_SIZE=${LLAMA3_SIZE:-"8B"}
export EVAL_TARGET=3.3 EVAL_FREQ=12288 export EVAL_TARGET=3.3 EVAL_FREQ=12288
export LR="1e-3" END_LR="1e-4" WARMUP_SAMPLES=4096 MAX_STEPS=1200000 export LR="1e-3" END_LR="1e-4" WARMUP_SAMPLES=2048 MAX_STEPS=1200000
export WARMUP_STEPS=$((WARMUP_SAMPLES / GBS)) export WARMUP_STEPS=$((WARMUP_SAMPLES / GBS))
export SAMPLES=$((MAX_STEPS * GBS)) export SAMPLES=$((MAX_STEPS * GBS))
export SEQLEN=${SEQLEN:-8192} export SEQLEN=${SEQLEN:-8192}
@@ -44,7 +44,7 @@ export SEED=${SEED:-5760}
export DATA_SEED=${DATA_SEED:-5760} export DATA_SEED=${DATA_SEED:-5760}
export JITBEAM=${JITBEAM:-3} export JITBEAM=${JITBEAM:-3}
export BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=1 export BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export FAKEDATA=${FAKEDATA:-1} BENCHMARK=${BENCHMARK:-10} export FAKEDATA=${FAKEDATA:-1} BENCHMARK=${BENCHMARK:-10}
if [ -z "$FULL_LAYERS" ]; then if [ -z "$FULL_LAYERS" ]; then
@@ -1,8 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
export PYTHONPATH="." export PYTHONPATH="."
export PATH="/opt/rocm-7.1.1/bin:$PATH" export ROCM_PATH=${ROCM_PATH:-/opt/rocm-7.1.1}
export ROCM_PATH="/opt/rocm-7.1.1" export PATH="$ROCM_PATH/bin:$PATH"
export DEV=${DEV:-AMD} export DEV=${DEV:-AMD}
export CHECK_OOB=0 export CHECK_OOB=0
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000 export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
@@ -26,7 +26,7 @@ export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
export SPLIT_W13=${SPLIT_W13:-0} export SPLIT_W13=${SPLIT_W13:-0}
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-0} export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-0}
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16" export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="float32"
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2} export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
export GBS=$((BS * GRADIENT_ACC_STEPS)) export GBS=$((BS * GRADIENT_ACC_STEPS))
@@ -35,7 +35,7 @@ export BASEDIR="/raid/datasets/c4-8b/"
export SMALL=1 export SMALL=1
export LLAMA3_SIZE=${LLAMA3_SIZE:-"8B"} export LLAMA3_SIZE=${LLAMA3_SIZE:-"8B"}
export EVAL_TARGET=3.3 EVAL_FREQ=12288 export EVAL_TARGET=3.3 EVAL_FREQ=12288
export LR="1e-3" END_LR="1e-4" WARMUP_SAMPLES=4096 MAX_STEPS=1200000 export LR="1e-3" END_LR="1e-4" WARMUP_SAMPLES=2048 MAX_STEPS=1200000
export WARMUP_STEPS=$((WARMUP_SAMPLES / GBS)) export WARMUP_STEPS=$((WARMUP_SAMPLES / GBS))
export SAMPLES=$((MAX_STEPS * GBS)) export SAMPLES=$((MAX_STEPS * GBS))
export SEQLEN=${SEQLEN:-8192} export SEQLEN=${SEQLEN:-8192}
@@ -44,6 +44,6 @@ export SEED=${SEED:-$RANDOM}
export DATA_SEED=${DATA_SEED:-5760} export DATA_SEED=${DATA_SEED:-5760}
export JITBEAM=${JITBEAM:-3} export JITBEAM=${JITBEAM:-3}
export BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=1 export BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
python3 examples/mlperf/model_train.py python3 examples/mlperf/model_train.py
@@ -17,7 +17,7 @@ export USE_ATOMICS=1
export ASM_GEMM=1 export ASM_GEMM=1
export WQKV=1 export WQKV=1
export MASTER_WEIGHTS=1 export MASTER_WEIGHTS=1
export FP8=1 export MXFP4=1
export ALLREDUCE_CAST=1 export ALLREDUCE_CAST=1
export FAST_CE=1 export FAST_CE=1
export FUSED_INPUT_QUANTIZE=1 export FUSED_INPUT_QUANTIZE=1
@@ -26,7 +26,7 @@ export FUSED_ADD_NORM_MUL_QUANTIZE=1
export FUSED_SILU_W13=1 export FUSED_SILU_W13=1
export SPLIT_W13=0 export SPLIT_W13=0
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16" export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="float32"
export DP=8 MP=1 BS=16 EVAL_BS=8 GRADIENT_ACC_STEPS=2 export DP=8 MP=1 BS=16 EVAL_BS=8 GRADIENT_ACC_STEPS=2
export GBS=$((BS * GRADIENT_ACC_STEPS)) export GBS=$((BS * GRADIENT_ACC_STEPS))
@@ -44,7 +44,7 @@ export SEED=$RANDOM
export DATA_SEED=$SEED export DATA_SEED=$SEED
export JITBEAM=3 export JITBEAM=3
export BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=1 export BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export LOGMLPERF=1 export LOGMLPERF=1
@@ -11,6 +11,7 @@ export DEVICE_IN_FUNCTION_BUG=1
export DEBUG=${DEBUG:-2} export DEBUG=${DEBUG:-2}
export HK_FLASH_ATTENTION=${HK_FLASH_ATTENTION:-1} export HK_FLASH_ATTENTION=${HK_FLASH_ATTENTION:-1}
export ASM_GEMM=${ASM_GEMM:-1} export ASM_GEMM=${ASM_GEMM:-1}
export GROUPED_MOE=${GROUPED_MOE:-1}
export ALL2ALL=${ALL2ALL:-1} export ALL2ALL=${ALL2ALL:-1}
export LATE_ALLREDUCE=${LATE_ALLREDUCE:-0} export LATE_ALLREDUCE=${LATE_ALLREDUCE:-0}
export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1} export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1}

Some files were not shown because too many files have changed in this diff Show More