感谢国家超算互联网(www.scnet.cn)邀请我参加谁是下一个“AI”跃人 - AI算力体验活动
(https://www.scnet.cn/home/subject/modular/index272.html)!
scnet这个平台吸引最我的地方就是他们提供异构加速卡AI,这张卡与L20算力相当,并且比L20有更大的显存,更低的价格:
可以看到异构加速卡AI对标的是L20,在算力和显存方面都是略胜一筹,但是L20凭借自家计算框架应该能弥补这些差距,所以我更加好奇的是异构加速卡AI能不能做到我们平时在N卡平台上能做到的事情?
所以,我对加速卡进行了如下测试:
使用resnet网络对加速卡测速
Llama3推理测试
使用PEFT框架对Llama3进行微调并推理
使用resnet网络对加速卡测速
我写了一个resnet网络的训练网络来测试这个显卡的性能。
测试代码:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # Only show error messages
import tensorflow as tf
from tensorflow.keras import layers, models
# Set GPU dynamic memory growth
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
try:
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
except RuntimeError as e:
print(e)
# Load CIFAR-100 dataset
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar100.load_data()
# Normalize data
x_train, x_test = x_train / 255.0, x_test / 255.0
# Define ResNet block
def resnet_block(inputs, num_filters, kernel_size=3, strides=1, activation='relu'):
x = layers.Conv2D(num_filters, kernel_size=kernel_size, strides=strides, padding='same')(inputs)
x = layers.BatchNormalization()(x)
if activation:
x = layers.Activation(activation)(x)
return x
# Define identity block
def resnet_identity_block(inputs, num_filters):
x = resnet_block(inputs, num_filters)
x = resnet_block(x, num_filters, activation=None)
x = layers.Add()([x, inputs])
x = layers.Activation('relu')(x)
return x
# Define convolution block
def resnet_conv_block(inputs, num_filters, strides=2):
x = resnet_block(inputs, num_filters, strides=strides)
x = resnet_block(x, num_filters, activation=None)
shortcut = layers.Conv2D(num_filters, kernel_size=1, strides=strides, padding='same')(inputs)
shortcut = layers.BatchNormalization()(shortcut)
x = layers.Add()([x, shortcut])
x = layers.Activation('relu')(x)
return x
# Build ResNet model
def build_resnet(input_shape, num_classes):
inputs = layers.Input(shape=input_shape)
x = resnet_block(inputs, 64)
x = resnet_conv_block(x, 128)
x = resnet_identity_block(x, 128)
x = resnet_conv_block(x, 256)
x = resnet_identity_block(x, 256)
x = resnet_conv_block(x, 512)
x = resnet_identity_block(x, 512)
x = layers.GlobalAveragePooling2D()(x)
outputs = layers.Dense(num_classes, activation='softmax')(x)
model = models.Model(inputs, outputs)
return model
# Create ResNet model
input_shape = (32, 32, 3)
num_classes = 100
model = build_resnet(input_shape, num_classes)
# Compile model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Train model
history = model.fit(x_train,
y_train,
epochs=10,
validation_data=(x_test, y_test),
batch_size=4*74)
# Evaluate model
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print(f'Test accuracy: {test_acc}')
下面是训练速度的比较截图:
图一:L20在训练的第一轮大概10秒
图二,异构加速卡AI的第一轮大概也是10秒(不知道什么问题,tensorflow在异构加速卡AI上只能跑完前向)
通过这个小测试,我觉得异构加速卡AI的性能和L20是差不多的。
Llama3推理测试
接着,我又在异构加速卡AI上面跑了llama的模型,同时模型是在平台的商城下载的
在平台的商城中购买模型,可以在几分钟之内把模型下载带到开发容器之中,这样的相比于从公网下载快了很多,可以节省不少开发时间。
大模型运行代码:
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import time
# 指定模型和分词器的本地路径
model_path = "/root/private_data/Llama3-8B-Chinese-Chat"
# 检查CUDA是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if torch.cuda.is_available():
print("模型在异构加速卡上运行")
else:
print("模型在CPU上运行")
# 加载分词器和模型
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float32).to(device)
# 定义生成对话的函数
def generate_response(prompt):
inputs = tokenizer(prompt, return_tensors="pt").to(device)
start_time = time.time() # 开始计时
outputs = model.generate(
inputs["input_ids"],
max_length=512,
num_beams=5,
no_repeat_ngram_size=2,
early_stopping=True,
top_k=50,
top_p=0.95,
temperature=0.7
)
end_time = time.time() # 结束计时
# 计算生成的 token 数
generated_tokens = outputs.size(1)
generation_time = end_time - start_time
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
tokens_per_second = generated_tokens / generation_time
return response, tokens_per_second
# 测试对话生成
prompts = ["你好, 你可以介绍一下你自己吗?"]
for prompt in prompts:
response, tokens_per_second = generate_response(prompt)
print(f"模型输出: {response}")
print(f"生成速度是: {tokens_per_second:.2f} tk/s")
运行效果:
我使用了transformers库来读取本地的大模型进行文本生成,这里我读取模型使用的是FP32的数据精度。凭借着异构加速卡AI 64GB的大显存,FP32的读取也是不在话下。
使用PEFT框架对Llama3进行微调并推理
异构加速卡AI虽然有64GB显存,但是毕竟不是很热门的加速卡,它的兼容性是一个很致命的问题。但是好在异构加速卡AI下的Pytorch目前一切正常。所以为了在这上面对显卡进行微调,我选择了PEFT这个框架对Llama3-8B-Chinese-Chat进行微调。
明确一下微调的目的,微调的目的是:打造一个个性化的语言模型,可以使用《甄嬛传》的语气回答问题,类似角色扮演。训练方法使用lora进行微调。
先来看一下训练数据:
数据是《甄嬛传》中的角色对话数据,使用json作为保存格式。
这里我们先导入一下模块,设置一下模型的路径和保存路径。这里我原本以为私人空间也就是平台的/root/private_data这个路径下加载数据集会让模型的训练变慢,但是在这个文件夹下加载速度还是很不错的。感觉负载不大的情况下完全可以直接在这个文件夹下面进行训练。
这上面四张图片我做了这几件事:首先我加载了模型了分词器,接着我使用pandas加载了json数据集,然后我定义了一个函数,这个函数把json数据集中的对话通过分词器进行编码,最后把训练数据存储在变量中等待训练的调用
想要改变大模型的生成风格,我们不需要进行全量微调,我们可以直接抄作业。"q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"这几个模块都是大模型中对语言风格影响较大的模块,对他们进行lora训练可以控制语言风格。
确定需要微调的模块之后,简单设置一下训练参数,我们开始对模型进行训练。
训练的过程没有出现什么意外,异构加速卡AI对pytorch的兼容性还是很强的,即使是调用PEFT这种第三方的框架依然可以正常工作,说实话我真的很意外。
训练完成后,我们对训练结果进行保存
总的来说,微调模型的过程中我感觉十分的顺利,异构加速卡AI在使用的过程中没有出现很致命的错误,异构加速卡AI对pytorch兼容性很好。
训练好了lora模型之后,我们在使用的时候需要先加载微调之前的模型,然后再把lora当做一个插件一样安装上去。
我写了一个推理的脚本来测试这次微调之后的模型的效果,从这里可以看到模型的数据已经被我训练的数据影响成《甄嬛传》的风格了。
推理过程也没有出现什么意外,我觉得这是对异构加速卡AI最好的评价了。异构加速卡AI对pytorch的兼容性很好,大部分pytorch程序都可以在异构加速卡AI上运行。
总结
一个体验很好的地方就是平台内置数据集商城和模型商城,如图五,在我使用平台的过程中发现即使是coco2017这样的数据集也可以在几分钟之内下载到用户空间,所以我推测平台的商城和我们的用户空间是通过内网传输,所以数据集、模型的下载特别快,体验非常好!
同时我们在使用平台上面的算力进行开发的时候也有多种环境可以选择:
这极大的减少了我们开发人员的部署环境时的困难,时间就是生命!
同时异构加速卡AI完全支持pytorch在日常开发中的使用,并用于和L20差不多的算力和比L20多10几G的显存!并且价格还更加便宜!
AI算力不够用?参与 谁是下一个“AI”跃人 -AI体验推介活动,赢取千元算力券!(https://www.scnet.cn/home/subject/modular/index270.html)
如果你也想使用这个平台!那么你绝对会对这个活动感兴趣,这个活动免费赠送算力,你可以边做你的项目,边完成这个活动:
活动内容并不复杂,具体流程就是:使用scnet平台开发 -> 适当提交一些成果(可以是跑跑大模型、运行训练代码) -> 平台审查(如不行会给修改意见) -> 根据评分送算力券!