AWS Neuron 随笔

[Lifan]

2025/01/11

1. Overview

AWS Neuron 是一个为了 AWS inferential 和 AWS Trainium 芯片设计的 SDK。它提供了一整套工具用于运行 deep learning 和 generative AI 任务。这个SDK 包括了 compiler, runtime, training and inference libraries, and profiling tools。现在业界部署模型一般都是使用 GPU,而 Neuron 算是提供了另一种选择,用户可以使用 SDK 在这些 AWS AI Chip 上部署自己的模型。 [reference]

2. Neuron Software Stack

上面这张图[source] 很好的列出了 Neuron 相关的生态链。Neuron SDK 里面分为那么几个大块,Inference/Training Libraries, Frameworks, Compiler, Runtime, Tools。

2.1 Inference/Training Libraries

从一个使用 neuron sdk 来部署模型的角度来说,这一部分的东西是开发者更容易直接接触的,它们本身已经支持了一些模型例如 llama,mistral 等,所以开发者如果只是使用这些 open source 的模型,就可以直接使用。

对于 Inference 来说,主要使用的是 Transformers NeuronX 和 NxD Inference, 它们都是开源的 Pytorch-based inference library。

对于 Training 来说,主要使用的是 NxD Training 这个 library,没有亲身使用过,就不多说了。

另外可以提一点是, inference 和 training 很多的 code 是可以 share 的,NxD Inference 和 NxD Training 都是 based on NxD Core 这个 library 的。

2.2 Frameworks

Pytorch Neuron, JAX Neuron, TensorFlow Neuron 都是属于这一块。这些 library 方便了开发者把原生的 PyTorch 等模型 在 Neuron Device 上运行,减少了迁移成本。

2.3 Compiler

Compiler 的作用是接收 ML models (可以是 Pytorch,TensorFlow, XLA HLO) 等,然后对它进行优化生成一个可执行文件 NEFF (Neuron Executable File Format)。然后这个 NEFF 可以被 Runtime 使用。

2.4 Runtime

Runtime 由 kernel driver 和 C/C++ libraries 构成,由于我没真的接触,不多说。大概知道它用于 load compiler 的产物(NEFF) 以及和 Neuron 硬件沟通,例如分配硬件资源、调度计算任务等就好了。

2.5 Tools

Tools 分为两类

3. A Closer Look at Transformers NeuronX

3.1 Overview

稍微深入看一眼 Transformers NeuronX 这个 lib。作为一个之前没有真正做过 ML 的人,刚开始 debug 这些代码的时候困扰我的一个点是,我并不清楚 XLA HLO 是干什么的,经常断点走着走着不清楚走去哪了。所以为了便于理解,我后来把这个 lib 里面的代码分成了两部分。

https://arxiv.org/pdf/2305.07716

举个例子,上面是一个 decoder only 的 transformer 架构,在对这个模型做 inference 的过程中,计算量主要来自于 Transformer Block 的 N 次计算。以 llama 3 70b 为例,N = 80,所以这是非常大量的计算,这时候就是需要 GPU 或者 Neuron 来并行计算,加速整个过程。

而这个 lib 已经 implement 了各种模型的架构,在 load 模型的时候,这些大量计算的步骤会被构建成计算图,并经过 compiler 编译成 NEFF 文件,NEFF 文件在 inference 时会被 Runtime 使用,实现 neuron device 的利用和并行计算。

除了提供模型的加载和并行计算,它还会提供一些其他的功能以便开发者可以直接使用。例如:

这些步骤通常不是并行计算,debug 的时候也相对容易。

3.2 Code Example

import time
import torch
from transformers import AutoTokenizer
from transformers_neuronx import LlamaForSampling

# load meta-llama/Llama-2-13b to the NeuronCores with 24-way tensor parallelism and run compilation
neuron_model = LlamaForSampling.from_pretrained('Llama-2-13b', batch_size=1, tp_degree=24, amp='f16')
neuron_model.to_neuron()

# construct a tokenizer and encode prompt text
tokenizer = AutoTokenizer.from_pretrained('Llama-2-13b')
prompt = "Hello, I'm a language model,"
input_ids = tokenizer.encode(prompt, return_tensors="pt")

# run inference with top-k sampling
with torch.inference_mode():
    start = time.time()
    generated_sequences = neuron_model.sample(input_ids, sequence_length=2048, top_k=50)
    elapsed = time.time() - start

generated_sequences = [tokenizer.decode(seq) for seq in generated_sequences]
print(f'generated sequences {generated_sequences} in {elapsed} seconds')

可以看到这个代码还是很短的 source

以这个为 starting point 并且记得 3.1 所说的两部分,就可以尝试 run 一个模型的 inference task 然后更深入的往下看代码了。

4. Closing Notes

这还是一篇写给自己看的随笔,回想这一两年,确实学习到了挺多东西。在使用这些 SDK 的过程中,记得一开始很容易陷入 debug 的 旋涡,因为当时过于关注细节,没有一个 big picture。回头看,实际上一开始就问问自己整个 workflow 是怎么 work 的,就算一开始还是什么都不懂,在遇到 blocker 的时候也会更容易找到往哪个方向去探索。

Ok cool, 这个工作就算告一段落,相信以后 Neuron SDK 也会不断迭代,并且有更多新的 feature。看看它可以不可以 抢下 GPU 的一块蛋糕吧。