☰
用 STREAM 内存带宽基准检验 wasm3:构建、运行与解读
2026/9/27 7:20:14 网站建设 项目流程
  • 解释器
  • 嵌入式
  • 语言运行时

【免费下载链接】wasm3

🚀 A fast WebAssembly interpreter and the most universal WASM runtime

项目地址:https://gitcode.com/gh_mirrors/wa/wasm3
点击查看免费下载

本篇文章围绕仓库 test/wasi/stream/ 目录下的 STREAM 5.10 内存带宽基准展开,讲解它如何被编译成 WASI 模块、如何在 wasm3 解释器上运行,以及仓库的测试与基准框架如何利用它验证引擎的正确性与性能。读完你可以独立完成 stream.wasm 的重编译、运行、结果校验,并借助run-bench.py对 wasm3 的四种内存内核吞吐进行量化对比。

1. STREAM 基准是什么

STREAM 是 John D. McCalpin 编写的经典内存带宽基准程序(本仓库使用 5.10 版本),用于测量内存子系统在简单计算内核下的数据传输速率(MB/s)。它不测 CPU 浮点峰值,而是测"数据搬运"能力——因为复制、缩放、加法等操作在现代 CPU 上往往被内存带宽所限。

仓库中的 test/wasi/stream/ 目录包含三个文件:

  • README.md:构建与运行说明(本篇文章的主体依据);
  • stream.c:STREAM 5.10 的完整 C 源码;
  • stream.wasm:已预编译好的 WASI 模块,可直接运行。

1.1 四个测量内核

stream.c 中定义了四个经典内核(stream.c):

内核标签操作每个元素搬运字节数
CopyCopy:c[j] = a[j]2 × sizeof(STREAM_TYPE)
ScaleScale:b[j] = scalar * c[j]2 × sizeof(STREAM_TYPE)
AddAdd:c[j] = a[j] + b[j]3 × sizeof(STREAM_TYPE)
TriadTriad:a[j] = b[j] + scalar * c[j]3 × sizeof(STREAM_TYPE)

每个内核默认重复执行NTIMES = 10次,报告时跳过第一次迭代,取剩余迭代的最优时间(mintime)计算带宽,这保证了 warm-up 之后的最稳定读数。

1.2 默认规模与内存需求

  • STREAM_ARRAY_SIZE默认为 10000000(1000 万元素);
  • STREAM_TYPE默认为double(8 字节);
  • 三个数组a[]、b[]、c[],总内存需求约为3 × 8 × 10000000 = 240 MB。

README 中给出的 ~229 MiB 是程序自身按 MiB(1024 进制)计算的报告值(见 stream.c 中Total memory required的输出逻辑)。这意味着运行该基准要求宿主运行时能提供约 229 MiB 的线性内存——这正是检验 wasm3 大内存支撑能力的好机会。

2. 构建 stream.wasm:WASI SDK 编译详解

README 明确给出了构建方法,前提是安装 WASI SDK 34 及以上版本,并设置环境变量$WASI_SDK_PATH:

$WASI_SDK_PATH/bin/clang -mcpu=lime1 -g0 -O3 -Wl,--strip-all stream.c -o stream.wasm

各参数含义如下:

参数作用
-mcpu=lime1针对 Wasm 的 Lime1 CPU 模型优化(WASI SDK 的 wasm32 目标)
-g0不生成调试信息,减小模块体积
-O3最高优化等级,让 clang 产出高效 Wasm 指令
-Wl,--strip-all链接阶段剥离符号表,进一步缩小体积

2.1 可选的编译期调优宏

stream.c 头部注释(stream.c)说明了一组可用-D覆盖的预处理宏,它们无需改源码即可调整基准规模:

# 调整数组元素个数(默认 10M,例如改为 100M) $WASI_SDK_PATH/bin/clang -O3 -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M.wasm # 调整迭代次数(默认 10,最小 2) $WASI_SDK_PATH/bin/clang -O3 -DNTIMES=7 stream.c -o stream.wasm # 调整数组对齐偏移(大数组接近 2 的幂时有助于对齐测试) $WASI_SDK_PATH/bin/clang -O3 -DOFFSET=56 stream.c -o stream.wasm # 改用单精度 float(会改变最小数组尺寸要求) $WASI_SDK_PATH/bin/clang -O3 -DSTREAM_TYPE=float stream.c -o stream.wasm

需要提醒的是:STREAM_ARRAY_SIZE越大,wasm3 需要为模块分配的线性内存就越多;若调得过高,需确认宿主环境内存足够。此外 stream.c 中使用了gettimeofday等 POSIX 接口,正是依靠 WASI 的时钟与系统调用能力才能在沙箱内计时。

2.2 为什么能编译成 WASI 模块

stream.c 依赖的printf、gettimeofday等库函数,由 WASI SDK 自带的 wasi-libc 提供。wasm3 通过其 WASI 实现(默认构建采用uvwasi,见 CMakeLists.txt;Wasm 自托管构建采用metawasi,见 CMakeLists.txt)在宿主侧为这些系统调用提供实现,从而让纯计算型基准也能以标准 WASI 应用的形式运行。

3. 在 wasm3 上运行

先按 docs/Development.md 的说明构建好 wasm3(产物默认为build/wasm3),然后从仓库根目录执行:

./build/wasm3 test/wasi/stream/stream.wasm

若在test/wasi/stream/目录内运行,则按 README 给出的相对路径写法:

../../../build/wasm3 stream.wasm

程序会输出类似如下的结果(数值依机器而异):

------------------------------------------------------------- STREAM version $Revision: 5.10 $ ------------------------------------------------------------- This system uses 8 bytes per array element. ... Array size = 10000000 (elements), Offset = 0 (elements) Memory per array = 76.3 MiB (= 0.1 GiB). Total memory required = 228.9 MiB (= 0.2 GiB). Each kernel will be executed 10 times. The *best* time for each kernel (excluding the first iteration) will be used to compute the reported bandwidth. ... Function Best Rate MB/s Avg time Min time Max time Copy: XXXX.X x.xxxxxx x.xxxxxx x.xxxxxx Scale: XXXX.X x.xxxxxx x.xxxxxx x.xxxxxx Add: XXXX.X x.xxxxxx x.xxxxxx x.xxxxxx Triad: XXXX.X x.xxxxxx x.xxxxxx x.xxxxxx ------------------------------------------------------------- Solution Validates: avg error less than 1e-13 on all three arrays -------------------------------------------------------------

3.1 计时精度提示

程序会调用checktick()测量系统时钟粒度(stream.c),并提示"每个测试至少应获得 20 个时钟 tick"。若clock granularity/precision输出过大且测试时长不足,说明数组规模偏小或计时器精度不够,应增大STREAM_ARRAY_SIZE重试。

3.2 结果校验:Solution Validates

STREAM 的一大特点是自带结果校验。checkSTREAMresults()(stream.c)会在计时结束后,用标量方式重放整个初始化、预热与内核循环,得到期望值aj、bj、cj,再与数组实测值逐元素比较平均相对误差:

  • double模式下容差epsilon = 1e-13;
  • float模式下容差epsilon = 1e-6。

只有三个数组的平均相对误差都小于容差,才会打印Solution Validates: avg error less than ... on all three arrays。这保证了即使测得的时间数据只是参考信息,计算正确性本身是被严格验证的——正如 README 所说:"The test suite only checks that it validates its own results, so the reported rates are informational."

4. 与仓库测试套件的集成

4.1 WASI 回归测试

stream.wasm 是 test/run-wasi-test.py 的 11 个 WASI 负载之一。测试定义(run-wasi-test.py):

{ "name": "STREAM", "wasm": "./wasi/stream/stream.wasm", "expect_pattern": "----*Solution Validates:*on all three arrays*----*" },

运行全部 WASI 测试:

# 在 test/ 目录下 python3 run-wasi-test.py

脚本默认执行../build/wasm3,可用--exec指定其他解释器甚至其他引擎(如wasmtime、wasmer,见 docs/Testing.md)。STREAM 负载的关键点在于:脚本不比对 MB/s 数值,只断言输出中出现Solution Validates,与 README 的表述完全一致——测试套件关心的是模块能否正确运行并自校验通过,速率仅供人工参考。

4.2 性能基准

在 test/run-bench.py 中,stream 是独立的 benchmark 工作负载,其定义会正则解析四种内核的速率(run-bench.py):

{ "name": "stream", "wasm": "./wasi/stream/stream.wasm", "expect": "Solution Validates", "metrics": [("stream-copy", "re", r"^Copy:\s+([0-9.]+)"), ("stream-scale", "re", r"^Scale:\s+([0-9.]+)"), ("stream-add", "re", r"^Add:\s+([0-9.]+)"), ("stream-triad", "re", r"^Triad:\s+([0-9.]+)")], },

基准前先断言输出包含Solution Validates(保证结果有效),再提取四行内核速率。可以只针对 stream 跑对比:

# 在 test/ 目录下 ./run-bench.py --exec "plain=../build/wasm3" \ --exec "metered=../build/wasm3 --gas-limit 1e12" \ --filter 'stream' --rounds 5

run-bench.py会把每轮命令交错并轮换顺序执行,消除机器漂移带来的不公平(见 run-bench.py 的说明),最终输出各引擎在每个指标上的中位数速率、波动幅度(spread)以及以第一个引擎为基准的逐轮配对比值与几何均值。这对于评估"某项运行时参数(如 gas metering)到底让内存带宽打了多少折扣"非常直观。

4.3 相关文档定位

  • 完整的测试框架说明见 docs/Testing.md,其中 Benchmarking 一节 详细解释了run-bench.py的--exec、--filter、--cpu、--json、--list等参数;
  • wasm3 自身的性能表现讨论见 docs/Performance.md,其中同样以test/run-bench.py与test/run-wasi-test.py作为测量当前代码树的推荐手段。

5. 实操建议与注意事项

  1. 内存需求:默认 10M 元素的 stream.wasm 需要约 229 MiB 线性内存,运行时请确保系统有足够空闲内存;在极小内存的嵌入式环境运行前,应先用-DSTREAM_ARRAY_SIZE显著缩小规模。
  2. 速率仅作参考:解释器与原生执行的内存带宽天然存在差异,STREAM 自带的校验保证了数值正确,但 MB/s 数值本身不适合跨引擎直接横向宣传,更应作为同一构建/同一机器上的相对对比。
  3. 用--filter精准聚焦:run-bench.py --filter 'stream'可只跑这一项负载,配合--json导出每轮原始样本,便于做置信度分析。
  4. 保持构建工具链一致:重编译 stream.wasm 建议使用与 README 一致的 WASI SDK 34 与相同的 clang 参数,避免优化选项差异影响数值的可比性。

综上,test/wasi/stream/这份 README 虽短,却完整覆盖了"编译 → 运行 → 自校验 → 集成进测试/基准框架"的全链路。对 wasm3 的开发者而言,它既是一个可反复验证正确性的 WASI 回归负载,也是一把量化解释器内存吞吐的标尺。

  • 解释器
  • 嵌入式
  • 语言运行时

【免费下载链接】wasm3

🚀 A fast WebAssembly interpreter and the most universal WASM runtime

项目地址:https://gitcode.com/gh_mirrors/wa/wasm3
点击查看免费下载

相关推荐

上一篇:【亲测免费】 Camera Shakify 项目教程
下一篇:Contriever 项目使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询