我想先说一些事情:整个项目都运行在免费的Kaggle T4笔记本上,一个几乎一文不值的AWS EC2 t3.micro中继器以及公共互联网上。
没有A100 没有私人数据中心网络。
没有预算。
然而,ShardFlow v2.1在Qwen2.5-7B上击出28.10个TPS峰值,跨越了WAN上两个独立的云区.
这是故事是如何发生的, 具体地说,一个在v2.1中 解决,我没有看到来。
问题:在FP16中运行一个没有钱的7B模型A7B参数模型需要大约15GB的VRAM.
单相Kaggle T4拥有16GB.
从技术上讲,它很适合,勉强, 没有什么留下的KV缓存。
溶液为收音机并行主义:将模型分出两台机器.
节点0 (Iowa) 处理地层0至14. 1号节点(Oregon)处理地层14至28,外加LM头和最终验证.
他们通过在俄亥俄州的EC2 t3.micro上运行的TCP中继器互相交谈.
基线吞吐量与这个设置,没有诡计:4.92 TPS.
可用,但不快。
相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相 你生成一个符号,等待,生成另一个,等待。
每一次穿越广域网的往返都花费了~86msRTT.
每回1个信使,你一直在与网络作对.
投机解码器翻了这个 而不是一次发送一个令牌,你在当地运行一个微小的草稿模型来猜测前面的下一个K令牌.
然后把K猜想都寄给核查员 如果大模特儿同意其中的M,你已经在一次来回而不是一次中承诺过M的符号.
ShardFlow使用Quen2.5-0.5B作为草稿模型,运行于cuda:1的Node 0上而7B目标切片运行于cuda:0.
零VRAM争议.
起草者推荐了8名候选人,节点1同时验证所有候选人,每回平均获得4.07个信使而不是1个.
以急切模式进行投机解码:14.3个TPS峰值. 3x更好.
我当时以为天花板是14.3 网络是明显的瓶颈:不同州的两起Kaggle事件, 公用互联网路由之间的EC2中继。
你还能做什么?
然后,我更仔细地研究了模型草案的实际工作。
每轮产生8个候选代币意味着运行8个独立的前行通过0.5B型.
每道前传从一个Python回路发射大约1500个CUDA内核,一个接一个地发射.
问题是:每个CUDA内核在GPU上以2至5微秒执行.
但Python只需要8到10微秒就可以发出发射呼叫.
GPU闲置的时间比实际的计算要多.
每轮代发稿:112ms.
GPU闲置率:65%.
Python悄悄地谋杀了GPU的使用,我不知道.
CUDA Graphs: What they Are and Why they helped A CUDA Graph 是一次捕捉GPU操作序列并重放作为单一驱动调用的方法.
通常,每次你的模型进行前传时,Python都会发出上千个单个内核发射.
每个都是给CUDA驾驶员的单独电话.
管理费增加得很快, 特别是当你在循环时。
通过 CUDA Graphs,您可以捕捉0.5B草稿模型的整个前传:所有24个变压器层,LM头,为下个符号的正弦.
你这样做一次。
之后,重放整部作品需要司机拨打一通电话.
热道上无平通.
代用:112m至25m. 4.5x更快.
我每次尝试CUDA Graphs, 模型就开始循环:"The the the"。
显然有些事情是错的。
CUDA Graphs在创纪录的时间捕捉到准确的GPU内存地址.
如果在重放期间有收发机被重新定位,则图表会读取一个陈旧的地址,然后得到垃圾输出.
HuggingFace默认的KV缓存(DynamicCache)调用每个单个的符号步骤.
每次都会分配一个新的缓冲器 图表记录了旧地址。
重放从中读取.
产出:垃圾。
有四个变化固定了这个:
1.
静态缓存而不是动态缓存 .