char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
d30500b83
char/aliceai-t5-moe
1#!/bin/bash 2# llama.cpp Hexagon test entry script for QDC Linux IoT (BASH framework). 3# 4# Placeholders substituted by run_qdc_jobs.py (--platform linux) before upload: 5# {MODEL_URL} direct URL to a .gguf model file 6# {TEST_MODE} bench | backend-ops | all 7# 8# QDC extracts the artifact zip to /data/local/tmp/TestContent/ and invokes 9# this script via: /bin/bash /data/local/tmp/TestContent/run_linux.sh 10# Any files written under /data/local/tmp/QDC_logs/ are auto-uploaded. 11 12set +e 13umask 022 14 15LOG_DIR =/data/local/tmp/QDC_logs 16BUNDLE_DIR =/data/local/tmp/TestContent/llama_cpp_bundle 17MODEL_DIR =/data/local/tmp/gguf 18MODEL_PATH =" $ MODEL_DIR /model.gguf" 19RESULTS_XML =" $ LOG_DIR /results.xml" 20 21mkdir -p " $ LOG_DIR " " $ MODEL_DIR " 22# Redirect all parent-shell output to script.log so QDC auto-uploads it; 23# per-case runs still capture their own stdout/stderr into dedicated logs. 24exec > " $ LOG_DIR /script.log" 2 >&1 25 26echo "=== env ===" 27date -u 28uname -a 29pwd 30 31mount -o rw,remount /2 > /dev/null ||true 32 33cd " $ BUNDLE_DIR " || {echo "FATAL: bundle missing at $ BUNDLE_DIR " ;exit 1; } 34chmod +x bin/*2 > /dev/null 35export LD_LIBRARY_PATH =" $ BUNDLE_DIR /lib: $ LD_LIBRARY_PATH " 36export ADSP_LIBRARY_PATH =" $ BUNDLE_DIR /lib" 37export GGML_HEXAGON_EXPERIMENTAL =1 38 39echo "=== download model ===" 40MODEL_URL ="{MODEL_URL}" 41if [ -z" $ MODEL_URL " ];then 42echo "No model URL provided, skipping download" 43elif [ ! -f" $ MODEL_PATH " ];then 44curl -L -fS --retry 3--retry-delay 5-o " $ MODEL_PATH " " $ MODEL_URL " 45curl_rc =$ ? 46if [$ curl_rc -ne 0 ];then 47echo "FATAL: model download failed (rc= $ curl_rc )" 48exit 1 49fi 50ls -la " $ MODEL_PATH " 51fi 52 53# --------------------------------------------------------------------------- 54# JUnit XML helpers 55# --------------------------------------------------------------------------- 56 57xml_open () { 58printf '%s\n' \ 59'<?xml version="1.0" encoding="utf-8"?>' \ 60"<testsuites>" \ 61"<testsuite name=\"llama_cpp_linux\">" \ 62> " $ RESULTS_XML " 63} 64 65xml_close () { 66printf '%s\n' '</testsuite>' '</testsuites>' >> " $ RESULTS_XML " 67} 68 69xml_case_pass () { 70 localclassname =$ 1 name =$ 2 71printf '<testcase classname="%s" name="%s"/>\n' " $ classname " " $ name " >> " $ RESULTS_XML " 72} 73 74xml_case_fail () { 75 localclassname =$ 1 name =$ 2 rc =$ 3 logfile =$ 4 76 { 77printf '<testcase classname="%s" name="%s">\n' " $ classname " " $ name " 78printf '<failure message="exit %s"><![CDATA[\n' " $ rc " 79tail -c 4096" $ logfile " 2 > /dev/null| sed 's/]]>/]] >/g' 80printf '\n]]></failure>\n</testcase>\n' 81 }>> " $ RESULTS_XML " 82} 83 84# Map backend name -> "NDEV --device" pair. "none" means no offload (CPU). 85backend_env () { 86case " $ 1 " in 87 cpu)echo "0 none" ;; 88 gpu)echo "0 GPUOpenCL" ;; 89 npu)echo "1 HTP0" ;; 90esac 91} 92 93backend_log_name () { 94case " $ 1 " in 95 cpu)echo "cpu" ;; 96 gpu)echo "gpu" ;; 97 npu)echo "htp" ;; 98esac 99} 100 101 102backend_device_name () { 103case " $ 1 " in 104 cpu)echo "none" ;; 105 gpu)echo "GPUOpenCL" ;; 106 npu)echo "HTP0" ;; 107esac 108} 109 110# Append a diagnostic block when a per-case `timeout N` fires (rc=124). The 111# naked log file at that point usually just ends mid-OpenCL-init with no 112# stderr, which is hard to read in CI summaries. 113note_timeout_if_triggered () { 114 localrc =$ 1 budget =$ 2 log =$ 3 115 [" $ rc " -eq 124 ] ||return 0 116 { 117printf '\n' 118printf '=== TIMEOUT after %ss ===\n' " $ budget " 119printf 'uptime: ' ;uptime 2 > /dev/null 120printf 'free -m:\n' ;free -m 2 > /dev/null 121printf 'loadavg: ' ;cat /proc/loadavg2 > /dev/null 122 }>> " $ log " 123} 124 125completion_extra_args () { 126case " $ 1 " in 127 cpu)echo "--device none --ctx-size 2048 -no-cnv -n 32 --seed 42" ;; 128 gpu)echo "--device GPUOpenCL --ctx-size 2048 -no-cnv -n 32 --seed 42" ;; 129 npu)echo "--device HTP0 --ctx-size 2048 -no-cnv -n 32 --seed 42 --ubatch-size 1024" ;; 130esac 131} 132 133run_completion_case () { 134 localname =$ 1 135 localparts =($( backend_env " $ name " ) ) 136 localndev =${ parts [0]} device =${ parts [1]} 137 localdevice_log_name =$( backend_device_name " $ name " ) 138 locallog =" $ LOG_DIR /llama_completion_ ${ device_log_name } .log" 139 localprompt =" $ LOG_DIR /bench_prompt.txt" 140echo 'What is the capital of France?' > " $ prompt " 141 localextra 142extra =$( completion_extra_args " $ name " ) 143echo "=== [completion: $ name ] llama-completion --device $ device (NDEV= $ ndev ) ===" 144timeout 600 env GGML_HEXAGON_NDEV=$ ndev ./bin/llama-completion \ 145-m " $ MODEL_PATH " \ 146-f " $ prompt " \ 147$ extra \ 148> " $ log " 2 >&1< /dev/null 149 localrc =$ ? 150note_timeout_if_triggered " $ rc " 600" $ log " 151if [$ rc -eq 0 ];then 152xml_case_pass "tests.test_bench_posix" "test_llama_completion[ $ name ]" 153else 154xml_case_fail "tests.test_bench_posix" "test_llama_completion[ $ name ]" " $ rc " " $ log " 155fi 156} 157 158run_bench_case () { 159 localname =$ 1 160 localparts =($( backend_env " $ name " ) ) 161 localndev =${ parts [0]} device =${ parts [1]} 162 locallog_suffix =$( backend_log_name " $ name " ) 163 locallog =" $ LOG_DIR /llama_bench_ ${ log_suffix } .log" 164 localubatch_arg ="" 165 [" $ name " ="npu" ]&& ubatch_arg ="--ubatch-size 1024" 166echo "=== [bench: $ name ] llama-bench --device $ device (NDEV= $ ndev ) ===" 167timeout 600 env GGML_HEXAGON_NDEV=$ ndev ./bin/llama-bench \ 168-m " $ MODEL_PATH " \ 169--device " $ device " \ 170-ngl 99 \ 171$ ubatch_arg \ 172-t 4 \ 173-p 128 \ 174-n 32 \ 175> " $ log " 2 >&1 176 localrc =$ ? 177note_timeout_if_triggered " $ rc " 600" $ log " 178if [$ rc -eq 0 ];then 179xml_case_pass "tests.test_bench_posix" "test_llama_bench[ $ name ]" 180else 181xml_case_fail "tests.test_bench_posix" "test_llama_bench[ $ name ]" " $ rc " " $ log " 182fi 183} 184 185run_backend_ops_case () { 186 localdtype =$ 1 187 locallog =" $ LOG_DIR /backend_ops_ ${ dtype } .log" 188 localpattern 189case " $ dtype " in 190 q4_0) 191# Matches Android: exclude a known-broken shape on NPU. 192pattern ='^(?=.*type_a=q4_0)(?!.*type_b=f32,m=576,n=512,k=576).*$' 193 ;; 194 *) 195pattern ="type_a= ${ dtype } " 196 ;; 197esac 198echo "=== [backend-ops: $ dtype ] test-backend-ops -b HTP0 -o MUL_MAT ===" 199timeout 600 env GGML_HEXAGON_NDEV=1 GGML_HEXAGON_HOSTBUF=0 ./bin/test-backend-ops \ 200-b HTP0-o MUL_MAT-p " $ pattern " \ 201> " $ log " 2 >&1 202 localrc =$ ? 203note_timeout_if_triggered " $ rc " 600" $ log " 204if [$ rc -eq 0 ];then 205xml_case_pass "tests.test_backend_ops_posix" "test_backend_ops_htp0[ $ dtype ]" 206else 207xml_case_fail "tests.test_backend_ops_posix" "test_backend_ops_htp0[ $ dtype ]" " $ rc " " $ log " 208fi 209} 210 211xml_open 212 213case "{TEST_MODE}" in 214 bench) 215for b in cpu gpu npu;do run_completion_case " $ b " ;done 216for b in cpu gpu npu;do run_bench_case " $ b " ;done 217 ;; 218 backend-ops) 219for d in mxfp4 fp16 q4_0;do run_backend_ops_case " $ d " ;done 220 ;; 221 all) 222for b in cpu gpu npu;do run_completion_case " $ b " ;done 223for b in cpu gpu npu;do run_bench_case " $ b " ;done 224for d in mxfp4 fp16 q4_0;do run_backend_ops_case " $ d " ;done 225 ;; 226 *) 227echo "FATAL: unsupported TEST_MODE={TEST_MODE}" 228 ;; 229esac 230 231xml_close 232echo "=== done ===" 233# Host parses results.xml to decide pass/fail. 234exit 0