openpilot v0.11.1 release

date: 2026-06-04T09:49:56
master commit: c0ab3550eca2e9daf197c46b7e4b24aa9637cf2e
This commit is contained in:
Vehicle Researcher
2026-06-04 09:50:05 -07:00
commit 6adb63b915
3381 changed files with 1044370 additions and 0 deletions
View File
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
if [ $# -eq 0 ]; then
echo "usage: $0 <pull-request-number>"
exit 1
fi
BASE="https://github.com/commaai/openpilot/pull/"
PR_NUM="$(echo $1 | grep -o -E '[0-9]+')"
curl -L $BASE/$PR_NUM.patch | git apply -3
+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
nmcli connection modify --temporary esim ipv4.route-metric 1 ipv6.route-metric 1
nmcli con up esim
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -e
if [ $# -eq 0 ]; then
echo "usage: $0 <pull-request-number>"
exit 1
fi
BASE="https://github.com/commaai/openpilot/pull/"
PR_NUM="$(echo $1 | grep -o -E '[0-9]+')"
BRANCH=tmp-pr${PR_NUM}
git branch -D -f $BRANCH || true
git fetch -u -f origin pull/$PR_NUM/head:$BRANCH
git switch $BRANCH
git reset --hard FETCH_HEAD
+212
View File
@@ -0,0 +1,212 @@
#!/usr/bin/env python3
"""Fetch CI results from GitHub Actions and Jenkins."""
import argparse
import json
import subprocess
import time
import urllib.error
import urllib.request
from datetime import datetime
JENKINS_URL = "https://jenkins.comma.life"
DEFAULT_TIMEOUT = 1800 # 30 minutes
POLL_INTERVAL = 30 # seconds
LOG_TAIL_LINES = 10 # lines of log to include for failed jobs
def get_git_info():
branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], text=True).strip()
commit = subprocess.check_output(["git", "rev-parse", "HEAD"], text=True).strip()
return branch, commit
def get_github_actions_status(commit_sha):
result = subprocess.run(
["gh", "run", "list", "--commit", commit_sha, "--workflow", "tests.yaml", "--json", "databaseId,status,conclusion"],
capture_output=True, text=True, check=True
)
runs = json.loads(result.stdout)
if not runs:
return None, None
run_id = runs[0]["databaseId"]
result = subprocess.run(
["gh", "run", "view", str(run_id), "--json", "jobs"],
capture_output=True, text=True, check=True
)
data = json.loads(result.stdout)
jobs = {job["name"]: {"status": job["status"], "conclusion": job["conclusion"],
"duration": format_duration(job) if job["conclusion"] not in ("skipped", None) and job.get("startedAt") else "",
"id": job["databaseId"]}
for job in data.get("jobs", [])}
return jobs, run_id
def get_github_job_log(run_id, job_id):
result = subprocess.run(
["gh", "run", "view", str(run_id), "--job", str(job_id), "--log-failed"],
capture_output=True, text=True
)
lines = result.stdout.strip().split('\n')
return '\n'.join(lines[-LOG_TAIL_LINES:]) if len(lines) > LOG_TAIL_LINES else result.stdout.strip()
def format_duration(job):
start = datetime.fromisoformat(job["startedAt"].replace("Z", "+00:00"))
end = datetime.fromisoformat(job["completedAt"].replace("Z", "+00:00"))
secs = int((end - start).total_seconds())
return f"{secs // 60}m {secs % 60}s"
def get_jenkins_status(branch, commit_sha):
base_url = f"{JENKINS_URL}/job/openpilot/job/{branch}"
try:
# Get list of recent builds
with urllib.request.urlopen(f"{base_url}/api/json?tree=builds[number,url]", timeout=10) as resp:
builds = json.loads(resp.read().decode()).get("builds", [])
# Find build matching commit
for build in builds[:20]: # check last 20 builds
with urllib.request.urlopen(f"{build['url']}api/json", timeout=10) as resp:
data = json.loads(resp.read().decode())
for action in data.get("actions", []):
if action.get("_class") == "hudson.plugins.git.util.BuildData":
build_sha = action.get("lastBuiltRevision", {}).get("SHA1", "")
if build_sha.startswith(commit_sha) or commit_sha.startswith(build_sha):
# Get stages info
stages = []
try:
with urllib.request.urlopen(f"{build['url']}wfapi/describe", timeout=10) as resp2:
wf_data = json.loads(resp2.read().decode())
stages = [{"name": s["name"], "status": s["status"]} for s in wf_data.get("stages", [])]
except urllib.error.HTTPError:
pass
return {
"number": data["number"],
"in_progress": data.get("inProgress", False),
"result": data.get("result"),
"url": data.get("url", ""),
"stages": stages,
}
return None # no build found for this commit
except urllib.error.HTTPError:
return None # branch doesn't exist on Jenkins
def get_jenkins_log(build_url):
url = f"{build_url}consoleText"
with urllib.request.urlopen(url, timeout=30) as resp:
text = resp.read().decode(errors='replace')
lines = text.strip().split('\n')
return '\n'.join(lines[-LOG_TAIL_LINES:]) if len(lines) > LOG_TAIL_LINES else text.strip()
def is_complete(gh_status, jenkins_status):
gh_done = gh_status is None or all(j["status"] == "completed" for j in gh_status.values())
jenkins_done = jenkins_status is None or not jenkins_status.get("in_progress", True)
return gh_done and jenkins_done
def status_icon(status, conclusion=None):
if status == "completed":
return ":white_check_mark:" if conclusion == "success" else ":x:"
return ":hourglass:" if status == "in_progress" else ":grey_question:"
def format_markdown(gh_status, gh_run_id, jenkins_status, commit_sha, branch):
lines = ["# CI Results", "",
f"**Branch**: {branch}",
f"**Commit**: {commit_sha[:7]}",
f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ""]
lines.extend(["## GitHub Actions", "", "| Job | Status | Duration |", "|-----|--------|----------|"])
failed_gh_jobs = []
if gh_status:
for job_name, job in gh_status.items():
icon = status_icon(job["status"], job.get("conclusion"))
conclusion = job.get("conclusion") or job["status"]
lines.append(f"| {job_name} | {icon} {conclusion} | {job.get('duration', '')} |")
if job.get("conclusion") == "failure":
failed_gh_jobs.append((job_name, job.get("id")))
else:
lines.append("| - | No workflow runs found | |")
lines.extend(["", "## Jenkins", "", "| Stage | Status |", "|-------|--------|"])
failed_jenkins_stages = []
if jenkins_status:
stages = jenkins_status.get("stages", [])
if stages:
for stage in stages:
icon = ":white_check_mark:" if stage["status"] == "SUCCESS" else (
":x:" if stage["status"] == "FAILED" else ":hourglass:")
lines.append(f"| {stage['name']} | {icon} {stage['status'].lower()} |")
if stage["status"] == "FAILED":
failed_jenkins_stages.append(stage["name"])
# Show overall build status if still in progress
if jenkins_status["in_progress"]:
lines.append("| (build in progress) | :hourglass: in_progress |")
else:
icon = ":hourglass:" if jenkins_status["in_progress"] else (
":white_check_mark:" if jenkins_status["result"] == "SUCCESS" else ":x:")
status = "in progress" if jenkins_status["in_progress"] else (jenkins_status["result"] or "unknown")
lines.append(f"| #{jenkins_status['number']} | {icon} {status.lower()} |")
if jenkins_status.get("url"):
lines.append(f"\n[View build]({jenkins_status['url']})")
else:
lines.append("| - | No builds found for branch |")
if failed_gh_jobs or failed_jenkins_stages:
lines.extend(["", "## Failure Logs", ""])
for job_name, job_id in failed_gh_jobs:
lines.append(f"### GitHub Actions: {job_name}")
log = get_github_job_log(gh_run_id, job_id)
lines.extend(["", "```", log, "```", ""])
for stage_name in failed_jenkins_stages:
lines.append(f"### Jenkins: {stage_name}")
log = get_jenkins_log(jenkins_status["url"])
lines.extend(["", "```", log, "```", ""])
return "\n".join(lines) + "\n"
def main():
parser = argparse.ArgumentParser(description="Fetch CI results from GitHub Actions and Jenkins")
parser.add_argument("--wait", action="store_true", help="Wait for CI to complete")
parser.add_argument("--timeout", type=int, default=DEFAULT_TIMEOUT, help="Timeout in seconds (default: 1800)")
parser.add_argument("-o", "--output", default="ci_results.md", help="Output file (default: ci_results.md)")
parser.add_argument("--branch", help="Branch to check (default: current branch)")
parser.add_argument("--commit", help="Commit SHA to check (default: HEAD)")
args = parser.parse_args()
branch, commit = get_git_info()
branch = args.branch or branch
commit = args.commit or commit
print(f"Fetching CI results for {branch} @ {commit[:7]}")
start_time = time.monotonic()
while True:
gh_status, gh_run_id = get_github_actions_status(commit)
jenkins_status = get_jenkins_status(branch, commit) if branch != "HEAD" else None
if not args.wait or is_complete(gh_status, jenkins_status):
break
elapsed = time.monotonic() - start_time
if elapsed >= args.timeout:
print(f"Timeout after {int(elapsed)}s")
break
print(f"CI still running, waiting {POLL_INTERVAL}s... ({int(elapsed)}s elapsed)")
time.sleep(POLL_INTERVAL)
content = format_markdown(gh_status, gh_run_id, jenkins_status, commit, branch)
with open(args.output, "w") as f:
f.write(content)
print(f"Results written to {args.output}")
if __name__ == "__main__":
main()
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env python3
from openpilot.system.hardware import HARDWARE
if __name__ == "__main__":
HARDWARE.set_power_save(False)
+63
View File
@@ -0,0 +1,63 @@
"""
wrapper that materializes symlinks in docs/ before build
we can delete this once zensical supports symlinks:
https://github.com/zensical/backlog/issues/55
"""
import os
import shutil
import signal
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
DOCS_DIR = REPO_ROOT / "docs"
SITE_DIR = REPO_ROOT / "docs_site"
sys.path.insert(0, str(REPO_ROOT))
# Local docs build helpers live under docs/ so they stay near the content
# source. The wrapper prunes them from docs_site/ after build.
sys.path.insert(0, str(DOCS_DIR))
def _materialize(docs: Path) -> dict[Path, str]:
originals: dict[Path, str] = {}
for link in docs.rglob("*"):
if not link.is_symlink():
continue
target = link.resolve()
if not target.is_file():
continue
originals[link] = os.readlink(link)
link.unlink()
shutil.copy2(target, link)
return originals
def _restore(originals: dict[Path, str]) -> None:
for link, target in originals.items():
link.unlink(missing_ok=True)
os.symlink(target, link)
def _raise_interrupt(*_):
raise KeyboardInterrupt
def _prune_site_output() -> None:
shutil.rmtree(SITE_DIR / "ext", ignore_errors=True)
def main() -> None:
signal.signal(signal.SIGTERM, _raise_interrupt)
originals = _materialize(DOCS_DIR)
try:
from zensical.main import cli
cli(standalone_mode=False)
if len(sys.argv) > 1 and sys.argv[1] == "build":
_prune_site_output()
finally:
_restore(originals)
if __name__ == "__main__":
main()
+129
View File
@@ -0,0 +1,129 @@
#!/usr/bin/env bash
set -e
YELLOW='\033[0;33m'
GREEN='\033[0;32m'
UNDERLINE='\033[4m'
BOLD='\033[1m'
NC='\033[0m'
BRANCH="master"
RUNS="20"
COOKIE_JAR=/tmp/cookies
CRUMB=$(curl -s --cookie-jar $COOKIE_JAR 'https://jenkins.comma.life/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
FIRST_LOOP=1
function loop() {
JENKINS_BRANCH="__jenkins_loop_${BRANCH}_$(date +%s)"
API_ROUTE="https://jenkins.comma.life/job/openpilot/job/$JENKINS_BRANCH"
for run in $(seq 1 $((RUNS / 2))); do
N=2
if [[ $FIRST_LOOP ]]; then
TEMP_DIR=$(mktemp -d)
GIT_LFS_SKIP_SMUDGE=1 git clone --quiet -b $BRANCH --depth=1 --no-tags git@github.com:commaai/openpilot $TEMP_DIR
git -C $TEMP_DIR checkout --quiet -b $JENKINS_BRANCH
echo "TESTING: $(date)" >> $TEMP_DIR/testing_jenkins
git -C $TEMP_DIR add testing_jenkins
git -C $TEMP_DIR commit --quiet -m "testing"
git -C $TEMP_DIR push --quiet -f origin $JENKINS_BRANCH
rm -rf $TEMP_DIR
FIRST_BUILD=1
echo ''
echo 'waiting on Jenkins...'
echo ''
sleep 90
FIRST_LOOP=""
fi
FIRST_BUILD=$(curl -s $API_ROUTE/api/json | jq .nextBuildNumber)
LAST_BUILD=$((FIRST_BUILD+N-1))
TEST_BUILDS=( $(seq $FIRST_BUILD $LAST_BUILD) )
# Start N new builds
for i in ${TEST_BUILDS[@]};
do
echo "Starting build $i"
curl -s --output /dev/null --cookie $COOKIE_JAR -H "$CRUMB" -X POST $API_ROUTE/build?delay=0sec
sleep 5
done
echo ""
# Wait for all builds to end
while true; do
sleep 30
count=0
for i in ${TEST_BUILDS[@]};
do
RES=$(curl -s -w "\n%{http_code}" --cookie $COOKIE_JAR -H "$CRUMB" $API_ROUTE/$i/api/json)
HTTP_CODE=$(tail -n1 <<< "$RES")
JSON=$(sed '$ d' <<< "$RES")
if [[ $HTTP_CODE == "200" ]]; then
STILL_RUNNING=$(echo $JSON | jq .inProgress)
if [[ $STILL_RUNNING == "true" ]]; then
echo -e "Build $i: ${YELLOW}still running${NC}"
continue
else
count=$((count+1))
echo -e "Build $i: ${GREEN}done${NC}"
fi
else
echo "No status for build $i"
fi
done
echo "See live results: ${API_ROUTE}/buildTimeTrend"
echo ""
if [[ $count -ge $N ]]; then
break
fi
done
done
}
function usage() {
echo ""
echo "Run the Jenkins tests multiple times on a specific branch"
echo ""
echo -e "${BOLD}${UNDERLINE}Options:${NC}"
echo -e " ${BOLD}-n, --n${NC}"
echo -e " Specify how many runs to do (default to ${BOLD}20${NC})"
echo -e " ${BOLD}-b, --branch${NC}"
echo -e " Specify which branch to run the tests against (default to ${BOLD}master${NC})"
echo ""
}
function _looper() {
if [[ $# -eq 0 ]]; then
usage
exit 0
fi
# parse Options
while [[ $# -gt 0 ]]; do
case $1 in
-n | --n ) shift 1; RUNS="$1"; shift 1 ;;
-b | --b | --branch | -branch ) shift 1; BRANCH="$1"; shift 1 ;;
* ) usage; exit 0 ;;
esac
done
echo ""
echo -e "You are about to start $RUNS Jenkins builds against the $BRANCH branch."
echo -e "If you expect this to run overnight, ${UNDERLINE}${BOLD}unplug the cold reboot power switch${NC} from the testing closet before."
echo ""
read -p "Press (y/Y) to confirm: " choice
if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
loop
fi
}
_looper $@
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
export FINGERPRINT="TOYOTA_COROLLA_TSS2"
export SKIP_FW_QUERY="1"
$DIR/../launch_openpilot.sh
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
FAIL=0
if grep -n '\(#\|//\)\([[:space:]]*\)NOMERGE' $@; then
echo -e "NOMERGE comments found! Remove them before merging\n"
FAIL=1
fi
exit $FAIL
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
FAIL=0
if grep '^#!.*python' $@ | grep -v '#!/usr/bin/env python3$'; then
echo -e "Invalid shebang! Must use '#!/usr/bin/env python3'\n"
FAIL=1
fi
if grep '^#!.*bash' $@ | grep -v '#!/usr/bin/env bash$'; then
echo -e "Invalid shebang! Must use '#!/usr/bin/env bash'"
FAIL=1
fi
exit $FAIL
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env bash
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
UNDERLINE='\033[4m'
BOLD='\033[1m'
NC='\033[0m'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
ROOT="$DIR/../../"
cd $ROOT
FAILED=0
IGNORED_FILES="uv\.lock|docs\/CARS.md"
IGNORED_DIRS="^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*"
function run() {
shopt -s extglob
case $1 in
$SKIP | $RUN ) return 0 ;;
esac
echo -en "$1"
for ((i=0; i<$((50 - ${#1})); i++)); do
echo -n "."
done
shift 1;
CMD="$@"
set +e
log="$((eval "$CMD" ) 2>&1)"
if [[ $? -eq 0 ]]; then
echo -e "[${GREEN}${NC}]"
else
echo -e "[${RED}${NC}]"
echo "$log"
FAILED=1
fi
set -e
}
function run_tests() {
ALL_FILES=$1
PYTHON_FILES=$2
run "ruff" ruff check $ROOT --quiet
run "check_added_large_files" python3 -m pre_commit_hooks.check_added_large_files --enforce-all $ALL_FILES --maxkb=120
run "check_shebang_scripts_are_executable" python3 -m pre_commit_hooks.check_shebang_scripts_are_executable $ALL_FILES
run "check_shebang_format" $DIR/check_shebang_format.sh $ALL_FILES
run "check_nomerge_comments" $DIR/check_nomerge_comments.sh $ALL_FILES
if [[ -z "$FAST" ]]; then
run "ty" ty check
run "codespell" codespell $ALL_FILES
fi
return $FAILED
}
function help() {
echo "A fast linter"
echo ""
echo -e "${BOLD}${UNDERLINE}Usage:${NC} op lint [TESTS] [OPTIONS]"
echo ""
echo -e "${BOLD}${UNDERLINE}Tests:${NC}"
echo -e " ${BOLD}ruff${NC}"
echo -e " ${BOLD}ty${NC}"
echo -e " ${BOLD}codespell${NC}"
echo -e " ${BOLD}check_added_large_files${NC}"
echo -e " ${BOLD}check_shebang_scripts_are_executable${NC}"
echo ""
echo -e "${BOLD}${UNDERLINE}Options:${NC}"
echo -e " ${BOLD}-f, --fast${NC}"
echo " Skip slow tests"
echo -e " ${BOLD}-s, --skip${NC}"
echo " Specify tests to skip separated by spaces"
echo ""
echo -e "${BOLD}${UNDERLINE}Examples:${NC}"
echo " op lint ty ruff"
echo " Only run the ty and ruff tests"
echo ""
echo " op lint --skip ty ruff"
echo " Skip the ty and ruff tests"
echo ""
echo " op lint"
echo " Run all the tests"
}
SKIP=""
RUN=""
while [[ $# -gt 0 ]]; do
case $1 in
-f | --fast ) shift 1; FAST="1" ;;
-s | --skip ) shift 1; SKIP=" " ;;
-h | --help | -help | --h ) help; exit 0 ;;
* ) if [[ -n $SKIP ]]; then SKIP+="$1 "; else RUN+="$1 "; fi; shift 1 ;;
esac
done
RUN=$([ -z "$RUN" ] && echo "" || echo "!($(echo $RUN | sed 's/ /|/g'))")
SKIP="@($(echo $SKIP | sed 's/ /|/g'))"
GIT_FILES="$(git ls-files | sed -E "s/$IGNORED_FILES|$IGNORED_DIRS//g")"
ALL_FILES=""
for f in $GIT_FILES; do
if [[ -f $f ]]; then
ALL_FILES+="$f"$'\n'
fi
done
PYTHON_FILES=$(echo "$ALL_FILES" | grep --color=never '.py$' || true)
run_tests "$ALL_FILES" "$PYTHON_FILES"
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -e
if [[ -f .git/hooks/post-commit.d/post-commit ]]; then
.git/hooks/post-commit.d/post-commit
fi
tools/op.sh lint --fast
echo ""
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
import os
import glob
from tinygrad.nn.onnx import OnnxPBParser
BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))
MASTER_PATH = os.getenv("MASTER_PATH", BASEDIR)
MODEL_PATH = "/selfdrive/modeld/models/"
class MetadataOnnxPBParser(OnnxPBParser):
def _parse_ModelProto(self) -> dict:
obj = {"metadata_props": []}
for fid, wire_type in self._parse_message(self.reader.len):
match fid:
case 14:
obj["metadata_props"].append(self._parse_StringStringEntryProto())
case _:
self.reader.skip_field(wire_type)
return obj
def get_checkpoint(f):
model = MetadataOnnxPBParser(f).parse()
metadata = {prop["key"]: prop["value"] for prop in model["metadata_props"]}
return metadata['model_checkpoint'].split('/')[0]
if __name__ == "__main__":
print("| | master | PR branch |")
print("|-| ----- | --------- |")
for f in glob.glob(BASEDIR + MODEL_PATH + "/*.onnx"):
fn = os.path.basename(f)
master = get_checkpoint(MASTER_PATH + MODEL_PATH + fn)
pr = get_checkpoint(BASEDIR + MODEL_PATH + fn)
print("|", fn, "|", f"[{master}](https://reporterv2.comma.life/{master})", "|", f"[{pr}](https://reporterv2.comma.life/{pr})", "|")
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
function fail {
echo $1 >&2
exit 1
}
function retry {
local n=1
local max=3 # 3 retries before failure
local delay=5 # delay between retries, 5 seconds
while true; do
echo "Running command '$@' with retry, attempt $n/$max"
"$@" && break || {
if [[ $n -lt $max ]]; then
((n++))
sleep $delay;
else
fail "The command has failed after $n attempts."
fi
}
done
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
retry "$@"
fi
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env sh
# Stop updater
pkill -2 -f system.updated.updated
# Remove pending update
rm -f /data/safe_staging/finalized/.overlay_consistent
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
# Send SIGHUP to updater
pkill -1 -f system.updated
Executable
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# testing the GPU box
export XDG_CACHE_HOME=/data/tinycache
mkdir -p $XDG_CACHE_HOME
cd /data/openpilot/tinygrad_repo/examples
while true; do
AMD=1 AMD_IFACE=usb python ./beautiful_cartpole.py
sleep 1
done
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
cd $DIR/../../tinygrad_repo
GREEN='\033[0;32m'
NC='\033[0m'
#export DEBUG=2
export PYTHONPATH=.
export AM_RESET=1
export AMD=1
export AMD_IFACE=USB
export AMD_LLVM=1
python3 -m unittest -q --buffer test.test_tiny.TestTiny.test_plus \
> /tmp/test_tiny.log 2>&1 || (cat /tmp/test_tiny.log; exit 1)
printf "${GREEN}Booted in ${SECONDS}s${NC}\n"
printf "${GREEN}=============${NC}\n"
printf "\n\n"
printf "${GREEN}Transfer speeds:${NC}\n"
printf "${GREEN}================${NC}\n"
python3 test/external/external_test_usb_asm24.py TestDevCopySpeeds
+89
View File
@@ -0,0 +1,89 @@
// gcc -O2 waste.c -lpthread -owaste
// gcc -O2 waste.c -lpthread -owaste -DMEM
#define _GNU_SOURCE
#include <stdio.h>
#include <math.h>
#include <sched.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <arm_neon.h>
#include <sys/sysinfo.h>
#include "../common/timing.h"
int get_nprocs(void);
double *ttime, *oout;
void waste(int pid) {
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(pid, &my_set);
int ret = sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
printf("set affinity to %d: %d\n", pid, ret);
// 128 MB
float32x4_t *tmp = (float32x4_t *)malloc(0x800000*sizeof(float32x4_t));
// comment out the memset for CPU only and not RAM
// otherwise we need this to avoid the zero page
#ifdef MEM
memset(tmp, 0xaa, 0x800000*sizeof(float32x4_t));
#endif
float32x4_t out;
double sec = seconds_since_boot();
while (1) {
for (int i = 0; i < 0x10; i++) {
for (int j = 0; j < 0x800000; j+=0x20) {
out = vmlaq_f32(out, tmp[j+0], tmp[j+1]);
out = vmlaq_f32(out, tmp[j+2], tmp[j+3]);
out = vmlaq_f32(out, tmp[j+4], tmp[j+5]);
out = vmlaq_f32(out, tmp[j+6], tmp[j+7]);
out = vmlaq_f32(out, tmp[j+8], tmp[j+9]);
out = vmlaq_f32(out, tmp[j+10], tmp[j+11]);
out = vmlaq_f32(out, tmp[j+12], tmp[j+13]);
out = vmlaq_f32(out, tmp[j+14], tmp[j+15]);
out = vmlaq_f32(out, tmp[j+16], tmp[j+17]);
out = vmlaq_f32(out, tmp[j+18], tmp[j+19]);
out = vmlaq_f32(out, tmp[j+20], tmp[j+21]);
out = vmlaq_f32(out, tmp[j+22], tmp[j+23]);
out = vmlaq_f32(out, tmp[j+24], tmp[j+25]);
out = vmlaq_f32(out, tmp[j+26], tmp[j+27]);
out = vmlaq_f32(out, tmp[j+28], tmp[j+29]);
out = vmlaq_f32(out, tmp[j+30], tmp[j+31]);
}
}
double nsec = seconds_since_boot();
ttime[pid] = nsec-sec;
oout[pid] = out[0] + out[1] + out[2] + out[3];
sec = nsec;
}
}
int main() {
int CORES = get_nprocs();
ttime = (double *)malloc(CORES*sizeof(double));
oout = (double *)malloc(CORES*sizeof(double));
pthread_t waster[CORES];
for (long i = 0; i < CORES; i++) {
ttime[i] = NAN;
pthread_create(&waster[i], NULL, (void *(*)(void *))waste, (void*)i);
}
while (1) {
double avg = 0.0;
double iavg = 0.0;
for (int i = 0; i < CORES; i++) {
avg += ttime[i];
iavg += 1/ttime[i];
printf("%4.2f ", ttime[i]);
}
double mb_per_sec = (16.*0x800000/(1024*1024))*sizeof(float32x4_t)*iavg;
printf("-- %4.2f -- %.2f MB/s \n", avg/CORES, mb_per_sec);
sleep(1);
}
}
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
import os
import time
import numpy as np
from multiprocessing import Process
from setproctitle import setproctitle
def waste(core):
os.sched_setaffinity(0, [core,])
m1 = np.zeros((200, 200)) + 0.8
m2 = np.zeros((200, 200)) + 1.2
i = 1
st = time.monotonic()
j = 0
while 1:
if (i % 100) == 0:
setproctitle(f"{core:3d}: {i:8d}")
lt = time.monotonic()
print(f"{core:3d}: {i:8d} {lt-st:f} {j:.2f}")
st = lt
i += 1
j = np.sum(np.matmul(m1, m2))
def main(gctx=None):
print("1-2 seconds is baseline")
for i in range(os.cpu_count()):
p = Process(target=waste, args=(i,))
p.start()
if __name__ == "__main__":
main()