Qwen1.5 是 Qwen2 的测试版,Qwen2 是一种基于 Transformer 的纯解码器语言模型,在大量数据上进行了预训练。与之前发布的 Qwen 相比,改进包括:
- 6 model sizes, including 0.5B, 1.8B, 4B, 7B, 14B, and 72B;
6 种型号尺寸,包括 0.5B、1.8B、4B、7B、14B 和 72B; - Significant performance improvement in human preference for chat models;
人类对聊天模型的偏好显著提高; - Multilingual support of both base and chat models;
对基本模型和聊天模型的多语言支持; - Stable support of 32K context length for models of all sizes
稳定支持 32K 上下文长度,适用于各种尺寸的模型 - No need of
trust_remote_code
.
不需要trust_remote_code
.
1. 咱们先从最小的模型 0.5B 开始
先看看模型参数
1 2 3 4 5 6 |
from transformers import AutoModelForCausalLM, AutoTokenizer device = "cuda" model = AutoModelForCausalLM.from_pretrained(MODEL_NAME).to(device) print(model) |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Qwen2ForCausalLM( (model): Qwen2Model( (embed_tokens): Embedding(151936, 1024) (layers): ModuleList( (0-23): 24 x Qwen2DecoderLayer( (self_attn): Qwen2SdpaAttention( (q_proj): Linear(in_features=1024, out_features=1024, bias=True) (k_proj): Linear(in_features=1024, out_features=1024, bias=True) (v_proj): Linear(in_features=1024, out_features=1024, bias=True) (o_proj): Linear(in_features=1024, out_features=1024, bias=False) (rotary_emb): Qwen2RotaryEmbedding() ) (mlp): Qwen2MLP( (gate_proj): Linear(in_features=1024, out_features=2816, bias=False) (up_proj): Linear(in_features=1024, out_features=2816, bias=False) (down_proj): Linear(in_features=2816, out_features=1024, bias=False) (act_fn): SiLU() ) (input_layernorm): Qwen2RMSNorm() (post_attention_layernorm): Qwen2RMSNorm() ) ) (norm): Qwen2RMSNorm() ) (lm_head): Linear(in_features=1024, out_features=151936, bias=False) ) |
- model.embed_tokens
- model.norm
- lm_head
- model.layers (总共24层)
我们可以将Transformer模型的每一层分配给一个GPU,每个GPU可能是多层
1.1. 多 GPU 模式加载这个小模型 0.5B
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-0.5B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 24 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "Give me a short introduction to large language model." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=512 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 |
python test02.py NUM_GPUS: 8 Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. A large language model is a type of artificial intelligence that can generate text based on the input given to it, without being explicitly programmed. It is commonly used in natural language processing (NLP) tasks such as language translation, chatbots, and language understanding. Large language models use a variety of techniques to learn from and generate text, including neural networks, transformers, and recurrent neural networks (RNNs). These models are trained on large datasets of labeled text data, which allows them to recognize patterns and structures within the language and generate new text that is similar to the training data. One of the key benefits of large language models is their ability to generate high-quality output quickly and consistently. They can be trained to understand the context and meaning behind the text, which makes them useful for applications where accuracy is critical. However, large language models also have some limitations. For example, they may struggle with complex or ambiguous sentences, and they may not always accurately capture the nuances of human language. Additionally, there is often a trade-off between the quality and speed of generated text, which can be challenging to balance when using large language models in real-world scenarios. Overall, large language models have had significant implications for fields such as natural language processing, machine learning, and computer vision, and continue to evolve and improve in terms of performance and adaptability. |
1.2. 试试长文章 0.5B
Qwen 1.5 来自官方的描述,说稳定支持 32K 上下文长度,适用于各种尺寸的模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-0.5B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 24 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个3万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=32000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
time python test03.py NUM_GPUS: 8 Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. 标题:《未来之光》 在未来的2078年,地球表面已经被一颗名为“星际火球”的未知星球完全覆盖。这颗星球上充满了奇异的现象,包括无限的生命体、时间旅行等。 主角是地球上的科学家艾伦,他决定带着他的团队去探索这个全新的世界。他们在星际火球上发现了一种新型的能源,这种能源是一种可以被人类无限次利用的物质,被称为“光子”。 然而,光子并非一帆风顺。他们首先遇到了一种无法克服的物理挑战——光子具有极高的能量密度,一旦进入人类的皮肤,就会瞬间燃烧。他们的研究方向是从如何将光子转化为能量进行使用开始。 艾伦和他的团队开始了漫长的实验,最终他们成功地制造出了这种新的能源。但是,光子的出现也带来了一些问题。他们需要找到一种方法来保护这种能源不被污染,同时也不能过度开发和利用。 在这个过程中,他们与一些外星文明进行了交流,他们向艾伦提供了先进的能源生产技术,并提出了对他们的保护方案。艾伦接受了这些提议,于是他们开始了一场对抗外星文明的战斗。 在激烈的战斗中,他们的团队遭受了重创,但他们并未放弃。他们通过智慧和勇气,成功地击败了外星文明,保护了他们的家园。 在战斗结束后,艾伦回到了地球上,他感谢所有的帮助,也感谢他的朋友们。他告诉人们,虽然科技的发展带来了很多便利,但也需要我们珍惜我们的资源,保护好我们的环境。 这就是《未来之光》,一个充满挑战又充满希望的故事。它告诉我们,只要我们敢于面对困难,勇于创新,就一定能够创造出属于自己的未来。 real 1m4.372s user 0m38.394s sys 0m8.390s |
1.3 试试 0.5B 单GPU加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-0.5B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个1万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=10000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果:
time python test05-0.5B-2.py
NUM_GPUS: 8
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
标题:星际危机
故事的主角是地球上的科学家,亚历山大。他被选为了创建一艘新的火星船,并开始了他的旅程。他的飞船名为“瑞尔德”,由先进的人造能源系统和先进的通讯设备组成。
一天,亚历山大在研究行星表面时发现了一个异常的现象,他的船突然失去了动力。他立刻启动了应急程序,用他的所有技术来修复这个故障。然而,当他在检查船上时,发现了一颗星球的表面覆盖着一层神秘的物质。这些物质似乎是一种能够吸收和转换能量的能源。亚历山大无法理解这是什么,他决定使用他的科学知识去寻找答案。
在接下来的几个月里,亚历山大和他的团队一起研究了这种物质的存在方式,他们发现这颗星球的表面有着一种奇特的能量释放器。这种能量释放器可以将星球的能量转化为光,然后以热能的形式传输到其他星球。亚历山大决定利用这个能源释放器,把所有的能量都集中在一次燃料释放上,希望这次能源释放能让他们的飞船恢复正常运行。
然而,在释放能量的过程中,飞船发生了严重的问题。它开始向太空喷射大量的燃料,但是燃料的燃烧没有完全熄灭。最后,亚历山大和他的团队被迫撤回了他们的飞船。他们的损失惨重,但他们的勇气和决心却使他们坚持了下来。
他们的任务不仅拯救了他们的飞船,也拯救了他们自己。亚历山大成为了人类历史上第一位成功地通过航天飞行改变世界的人物。他让人们明白,只要有坚定的决心和不懈的努力,就一定能够克服任何困难,实现自己的梦想。
尽管他们的冒险充满了挑战和风险,但他们仍然坚信,只要他们相信自己,就可以克服任何困难,实现自己的梦想。他们的故事激励着人们,让人们知道,只要有勇气和智慧,就能够改变世界。
real 1m43.555s
user 0m32.418s
sys 0m10.565s
2. 1.8B 模型,多GPU
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch import time MODEL_NAME = "Qwen/Qwen1.5-1.8B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 24 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time print(response) # 计算每秒处理的token数量 num_tokens_generated = generated_ids.shape[1] # 生成的token总数 tokens_per_second = num_tokens_generated / elapsed_time2 print(f"Tokens per second: {tokens_per_second}") print(f"Total Time: {elapsed_time} seconds") |
结果运行如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
time python test05-1.8B.py NUM_GPUS: 8 Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 63.05974817276001 seconds 标题:穿越时空的战士 在一个遥远的未来,人类社会已经发展到星际殖民的程度。在这个时代中,科技高度发达,人工智能、量子计算机和新能源技术的应用已超越了人类想象。然而,尽管人们生活在一个繁荣昌盛的世界里,但也面临着许多未知的挑战和危机。 在一次国际性的星际竞赛中,一支由科学家和工程师组成的精英团队赢得了比赛,他们成功地将一颗古老的星际石带到了人类的星球——地球。这颗星际石被称为“时间之碑”,据说它拥有无限的时间旅行能力,能够让探险者回到过去或未来的任何一个时刻。 随着星际石的到来,一系列惊人的事件接踵而至。科学家们利用石碑的力量探索并研究地球的历史与未来,发现了一些以前未被人类知晓的秘密。同时,石碑也引发了一场大规模的人类觉醒运动,人们开始质疑过去的错误决策和对未来未来的恐惧。越来越多的人选择离开家乡,踏上寻找答案和改变命运的旅程。 其中,一位名叫艾米丽的女性成为了这场变革的主要推动者。她是一位有着超凡智慧和坚韧意志的年轻科学家,也是石碑使用者之一。在石碑的帮助下,艾米丽解开了许多复杂的科学谜团,甚至在面对一些看似不可能解决的问题时,她凭借自己的勇气和决心找到了解决方案。 在经历了一系列生死考验后,艾米丽最终发现了人类社会的本质问题所在:我们的行为模式正在破坏我们自身和后代的生活质量。为了改变这个状况,艾米丽决定返回过去,阻止那些导致人类灭亡的行为。她的目标是唤醒人们对过去的反思,让人们意识到错误的决策,并采取行动来纠正它们。 艾米丽带着石碑回到了过去,但这次她不再是普通的科学家。她的身份被赋予了一项全新的使命——时间守护者。她不仅要保护时间碑不被滥用,还要通过自己的行动引导历史走向更美好的未来。在这个过程中,她遇到了各种各样的人,包括曾经被她拯救的幸存者、被历史遗忘的英雄和对艾米丽怀有敌意的人。 经过无数次的战斗和挫折,艾米丽逐渐成为了一个真正的领袖。她用自己的知识和勇气赢得了人们的信任和支持,带领着时间守护者的队伍走向了新的征途。他们的故事激励着每一个试图找到自我价值和改变世界的人,他们在追求真理的路上,共同创造了一个更加公正、和平、可持续的未来。 《穿越时空的战士》以艾米丽为代表的一群人的冒险旅程为线索,描绘了一个充满挑战和希望的未来世界。它通过深入探讨人类文明发展的历程,揭示出我们对过去和未来的认知局限,以及如何通过勇敢面对困难,实现自我成长和历史进步。这部作品既是一部科幻小说,又是一部关于人性、勇气和责任的故事,寓意深远,引人深思。 Generated Tokens: 584 Tokens per second: 6.205085219425609 Total Generation Time: 94.11635446548462 seconds real 2m41.035s user 1m48.874s sys 0m20.042s |
2.2 1.8B 模型,单GPU
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch import time MODEL_NAME = "Qwen/Qwen1.5-1.8B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
time python test05-1.8B-2.py NUM_GPUS: 8 Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 67.75650358200073 seconds 标题:宇宙之门 在遥远的银河系中,有一个名为艾利斯的星系,被誉为生命和科技的摇篮。艾利斯拥有众多美丽的星球,其中一颗名叫“纳鲁”的星球以其独特的环境和丰富的资源著称。 纳鲁星球表面覆盖着一层稀薄的冰层,犹如一片晶莹剔透的海洋,反射出无尽的蓝色星光。在这个寒冷的星球上,生活着一种智慧生物——纳鲁人,他们以自然的方式生存和发展,擅长种植和采集各种食物和资源,以此来维持他们的生存需求。 纳鲁人的科技远超其他同类物种,他们使用一种神秘的能量石块,可以将任何物质转化为能源,甚至可以直接操控和操纵整个星球的生态系统。这种能量石块被他们视为生命的基石,是他们智慧和力量的象征。 然而,纳鲁星球的秘密也逐渐浮出水面。据传说,纳鲁星球曾经是一颗巨大的恒星,由于某种未知的原因,它的核心发生了爆炸,强大的冲击波将它带到了这个荒凉而陌生的行星上。随着时间的推移,纳鲁星球上的生命逐渐进化,形成了独特的纳鲁文明。 然而,随着纳鲁文明的发展,他们的生活方式开始与地球人类截然不同。他们不再依赖于大自然的恩赐,而是通过科技手段控制和利用自然资源,甚至开始对其他星球进行殖民和开发。这种行为引起了纳鲁社会内部的矛盾和冲突,一些纳鲁人选择离开他们的家园,前往更加适合他们的星球生活。 在这个过程中,纳鲁科学家发现了一种新的能量石块,它不仅可以将纳鲁星球上的物质转化为能源,还可以修复纳鲁星球的核心,并恢复其曾经的光辉。但这种新能量石块并不简单,需要极高的技术含量和复杂的能量转化过程。 科学家们决定深入研究纳鲁星球的能量石块,希望从中获取突破性的科技突破。他们在星球的地下深处,挖掘出了一个神秘的能量矿脉,那里充满了奇特的能量晶体,每一个都蕴含着全新的能量转换原理。 经过多年的探索和实验,科学家们终于成功提取出了这种能量晶体,并将其应用于纳鲁星球的能量石块上。在无数次的试验和失败后,他们终于成功地将这种能量晶体转化为能源,使得纳鲁星球的能源得到了全面的恢复。 同时,科学家们也发现了纳鲁星球的核心发生了质的变化,核心中的核心石块已经失去了先前的能量波动,显示出明显的能量流失迹象。这无疑是一个重大的危机,如果继续按照现有的发展模式,纳鲁星球将会失去核心的力量,无法抵抗外部的入侵和威胁。 于是,科学家们决定重启纳鲁星球的核心石块,试图修复其原有的能量状态。他们进行了精心的模拟实验,最终成功地使核心石块重新获得了能量波动,使其再次具有了能量驱动的功能。 经过这次重置,纳鲁星球的人类社区开始重新崛起,他们用先进的科技手段改造了自己的生活环境,成功地抵御住了来自宇宙的各种外力侵袭。与此同时,纳鲁人也开始反思自己的发展模式,认识到过度开发和利用资源可能带来的严重后果,开始了可持续发展的道路。 纳鲁星球的故事告诉我们,科技并非万能,只有当人们尊重自然,合理利用自然资源,才能实现真正的可持续发展。在未来的世界里,纳鲁人将以此为鉴,继续在科技与环保之间寻找平衡,为构建和谐、繁荣的宇宙世界做出更大的贡献。 Generated Tokens: 715 Tokens per second: 29.989652369309425 Total Generation Time: 23.841556787490845 seconds real 1m34.365s user 0m41.232s sys 0m18.896s |
3. 4B 多GPU 加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch import time MODEL_NAME = "Qwen/Qwen1.5-4B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 40 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
time python test05-4B.py NUM_GPUS: 8 Loading checkpoint shards: 100%|███████████| 2/2 [03:07<00:00, 93.74s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 191.43567776679993 seconds 非常抱歉,作为一个AI文本生成模型,我无法一次性为您生成2万字的内容。但是,我可以帮助您开始写 作或者为您提供一些创意和灵感。请您告诉我更多的细节,例如故事的主题、主要角色等。这样我才能更好地为您提供帮助。 Generated Tokens: 54 Tokens per second: 2.780886061220365 Total Generation Time: 19.41827130317688 seconds real 3m35.004s user 0m56.952s sys 0m27.279s |
这么实在的么?再运行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
time python test05-4B.py NUM_GPUS: 8 Loading checkpoint shards: 100%|██████████████| 2/2 [02:10<00:00, 65.05s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 134.07681465148926 seconds 标题:《星际之眼》 在遥远的未来,地球文明已经达到了前所未有的高度。科技的发展,使得人类开始对宇宙进行探索,寻找新的生命形式和可能存在的外星文明。 在这个过程中,科学家们发现了一种名为"星际之眼"的神秘物质,它能够吸收和反射光线,使得任何生物都能通过它看到更远的地方,甚至可以看到其他星球的信息。 然而,这种"星际之眼"的出现,并没有让人类欣喜若狂,反而引起了恐慌。因为科学家们发现,这种物质可能会吸引外来生命的入侵,而且如果被滥用,也有可能对地球造成严重的破坏。 于是,一场关于如何保护和利用"星际之眼"的辩论开始了。一些人主张关闭"星际之眼",防止不必要的干扰;另一些人则认为应该继续研究和开发它的潜力,以推动人类的科技进步。 在这个争论中,一位名叫杰克的年轻人站了出来。他提出,人类不应该害怕未知,而应该勇于探索和挑战。他坚信,只有通过不断的努力和探索,人类才能找到真正的自我,才能改变世界。 于是,杰克决定独自一个人去探索"星际之眼"的秘密。经过了无数个日夜的努力,杰克终于成功地揭示了"星际之眼"的秘密。原来,这种物质其实是一种可以让人看到真实世界的能量,只要正确使用,就能够让人类更好地了解和探索宇宙。 在杰克的领导下,人类成功地利用了"星际之眼"的力量,进行了大量的宇宙探索。他们发现了更多的新星球,了解到了更多生命的奥秘,甚至找到了与地球相似的生命形式。 然而,这个过程并没有结束。由于地球的能量消耗过大,"星际之眼"开始逐渐衰退。为了保护这个珍贵的资源,杰克提出了一个大胆的计划:人类需要寻找新的能源,来替代"星际之眼"的能量。 在杰克的带领下,人类开始了艰难的寻找新能源的过程。他们研发出了各种先进的科技,试图找到一种能够替代"星际之眼"的新能量。经过无数次的失败和挫折,人类终于成功地找到了新的能源。 随着新能源的投入,"星际之眼"再次恢复了活力,人类的宇宙探索又重新进入了高潮。他们不仅找到了更多的新星球,还发现了更多的生命形式,甚至发现了一些与地球相似的生命形式。 最后,杰克带领人类成功地改变了世界。他们用自己的智慧和勇气,创造了一个全新的、充满希望的世界。人类不再是孤独的个体,而是成为了宇宙的一部分,与所有生命共同构成了一个和谐的宇宙。 这就是"星际之眼"的故事,一个关于探索、挑战和希望的故事。这个故事告诉我们,只要有梦想,有勇气,就一定能够实现自己的目标。 Generated Tokens: 566 Tokens per second: 2.9105564016095413 Total Generation Time: 194.46453595161438 seconds real 5m32.603s user 3m43.533s sys 0m36.183s |
3.2. 4B 单GPU
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch import time MODEL_NAME = "Qwen/Qwen1.5-4B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
time python test05-4B-2.py NUM_GPUS: 8 Loading checkpoint shards: 100%|██████████████| 2/2 [02:03<00:00, 61.86s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 127.5276780128479 seconds 对不起,由于篇幅限制,我无法为您提供一个完整的2万字的科幻小说。但我可以为您列出一个大致的情 节大纲和开头部分: 标题:星尘中的救赎 一、开头 在一颗遥远的星球上,科学家们发现了一种能够实现星际旅行的新技术——"光子引擎"。 二、情节发展 科学家们利用光子引擎探索宇宙,寻找可能存在的外星生命。然而,在一次冒险中,他们意外撞入了一个未知的黑洞。 三、转折点 当他们的飞船在黑洞边缘出现时,他们被吸入了黑洞,成为了一群被困在这个宇宙黑暗世界中的幸存者。 四、高潮 他们试图找到逃脱黑洞的方法,但是这个过程充满了困难和挑战。在这期间,他们发现了许多关于这个黑洞的秘密,甚至可能揭示出一个更大的宇宙秘密。 五、结局 在经历了无数的挫折和困难后,他们最终找到了逃脱黑洞的方法,并成功地回到了自己的星球。虽然他们失去了许多宝贵的时间,但他们也从这次经历中学到了许多宝贵的知识和经验。 这是一个大概的情节梗概,您可以根据这个梗概开始编写您的小说。我希望这能对您有所帮助! Generated Tokens: 248 Tokens per second: 23.96475511752906 Total Generation Time: 10.348530530929565 seconds real 2m20.750s user 0m42.449s sys 0m32.544s |
4. 7B的模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-7B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 32 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
time python test05-7B.py NUM_GPUS: 8 Loading checkpoint shards: 100%|█████████████████████| 4/4 [04:33<00:00, 68.44s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. 标题:星际尘埃的回响 在遥远的未来,地球已经步入了科技高度发达的新纪元。人类不再局限于蓝色星球,他们开拓了宇宙,建立了星际联盟,探索未知,寻找新的生存空间。在这个宏大的背景下,我们的故事就在一颗名为“赛博利亚”的殖民星球展开。 故事的主角,艾登·哈特,是一位年轻的星际探险家,他出生并成长于地球,但对那颗蓝色星球的记忆却如同遥远的童年梦 。他的梦想是找到传说中的"时间之源"——一种可以修复和延长生命的神秘能源,以拯救因资源枯竭而濒临崩溃的地球。 赛博利亚,一颗被废弃的矿星,曾是地球资源的宝库,但现在,它满目疮痍,生态系统严重受损。艾登受命带领一支小型探索队来到这里,他们的任务是揭开这颗星球的秘密,寻找可能存在的"时间之源"。 队伍由经验丰富的老队长莉亚、技术精湛的科学家凯瑟琳、以及勇敢无畏的机械师亚当组成。他们在赛博利亚的废墟中发现了一座古老的遗迹,其上的壁画描绘了一个神秘的循环图案,似乎暗示着时间的奥秘。 随着深入研究,他们发现这个星球曾遭受过一场灾难性的时空扭曲,导致时间流速异常,生物寿命缩短。而那个"时间之源",正是修复这种失衡的关键。然而,遗迹的守护者,一只古老智慧的机械生命体,警告他们,任何试图改变时间的行为都可能导致无法预料的后果。 在紧张的抉择中,艾登决定冒险,他相信只有通过理解和尊重自然,才能找到真正的救赎。他与机械生命体进行了一场智慧的博弈,最终赢得了它的信任,并成功启动了"时间稳定器",稳定了赛博利亚的时间流速。 修复后的赛博利亚开始恢复生机,生物种类繁多,绿色重新覆盖大地。艾登和他的团队成为了英雄,他们的事迹被星际联盟广为传颂。他们带着赛博利亚的重生秘密,回到了地球,为人类的未来带来了希望。 然而,故事并未结束,艾登明白,他们的使命是永恒的,他们将继续在星辰大海中探索,寻找更多的答案,保护这个宇宙的平衡。"时间之源"的故事,就像一首未完的交响曲,回荡在无尽的宇宙中,激励着每一个勇往直前的探险者。 这就是《星际尘埃的回响》——一个关于勇气、智慧和爱的科幻短篇,讲述了人类在面对困境时的坚韧与决心,以及对未知世界的无尽探索。 real 9m42.229s user 5m38.796s sys 1m7.439s |
从上面结果来看,
总花费时间为:9:42
模型加载时间为4:33
5分钟内生成了809个汉字,每秒大约2.6个汉字,速度还可以
5. 7B 的模型 device_map 使用 auto 方式
auto 方式仍然是使用多个GPU,只是分的比较平均
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-7B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map="auto") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
time python test05-7B-2.py NUM_GPUS: 8 Loading checkpoint shards: 100%|████████████| 4/4 [03:50<00:00, 57.51s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. 标题:星际迷航:未知的脉动 在遥远的未来,人类已经掌握了星际旅行,探索宇宙成为了日常生活的一部分。故事发生在一个名为"诺 兰星云"的神秘星系,这里隐藏着一个被遗忘的秘密。 主角,艾登·柯林斯,是一位年轻的星际探险家,他的父亲曾是著名的宇航员,因一次神秘任务失踪,留 下了一本尘封的日 记,里面记载了关于“脉动星球”的线索。这个星球据说拥有超越科技的能量源,吸引 了全球科学家的目光,却因其极端环境而无人能触及。 艾登决定挑战自我,带领一支由各领域精英组成的科研团队,踏上了寻找“脉动星球”的旅程。他们的飞船——“曙光号”,在浩渺的星海中穿行,遭遇了未知的黑洞、外星生物和恶劣的气候,但他们始终保持信念,勇往直前。 在一次意外中,他们发现了一个看似荒芜的星球——泰坦。这里的环境比想象中更为恶劣,但艾登发现星球表面的奇特纹理与父亲日记中的描述惊人相似。他坚信这就是“脉动星球”。 团队成员们开始深入研究,他们发现泰坦的土壤蕴含着一种前所未见的元素,这种元素释放出微弱但稳定的波动,似乎就是传说中的能量源。然而,这种波动也引来了一种名为“暗影生物”的威胁,它们对这种波动异常敏感,企图吞噬一切。 艾登决定冒险进入泰坦的核心地带,希望能找到控制波动的关键。他与团队成员并肩作战,面对生死考验。在生死边缘,他们发现了暗影生物的弱点,原来它们惧怕光,而泰坦核心深处正是最强烈的光源。 经过一场惊心动魄的决战,艾登成功激活了核心的能量,波动逐渐稳定下来。他带着宝贵的样本返回地球,人类社会因此迎来了新的科技革命,疾病、能源问题得到了前所未有的解决。 然而,艾登并未停下脚步,他继续探索宇宙,寻找更多未知的奥秘。他的故事激励着一代又一代的星际探险者,他们将父亲的勇气和智慧传承下去,继续在无尽的星海中寻找生命的起源和宇宙的真谛。 《星际迷航:未知的脉动》以艾登的冒险为线索,讲述了科技、友情和牺牲的力量,描绘了一个充满希望与挑战的未来世界。 real 8m51.094s user 5m25.063s sys 1m7.385s |
从上面结果来看,
总花费时间为:8:51
模型加载时间为3:50
5分钟内生成了840个汉字,每秒大约2.8个汉字,速度比前面快一点
6. 7B 的模型 只使用一个 GPU
7B 的模型只要14G左右,所以使用一个24G的 RTX 4090 是可以装载的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-7B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
time python test05-7B-3.py NUM_GPUS: 8 Loading checkpoint shards: 100%|█████████| 4/4 [04:17<00:00, 64.40s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. 标题:星际遗产 在未来的地球,人类已经成功地拓展到了星辰大海。在浩瀚的银河系边缘,隐藏着一颗名为“新绿洲”的神秘行星,它拥有适宜生命生存的特殊环境,被联合国命名为“星际遗产”。 故事的主角,艾登·亚历山大,是一位年轻的天体生物学家,他一直对新绿洲充满好奇,梦想揭开其背后 的秘密。他的父亲,一位退役的宇航员,曾在那里进行过一次探险,但那次任务后神秘失踪,留下了一个未解的谜团。 艾登决定继承父亲的遗志,踏上了寻找真相的旅程。他组建了一支由各领域精英组成的探险队伍,包括人工智能专家莉娜、地质学家罗伯特和军事出身的指挥官凯文。他们的目标是通过先进的太空船“曙光号”穿越虫洞,抵达新绿洲。 航行过程中,他们遭遇了未知的宇宙风暴,船员们面临生死考验。艾登凭借他的科学知识和团队的协作,成功稳定了飞船,但他们并未放弃对新绿洲的探索,反而更加坚定了决心。 抵达新绿洲后,他们发现了一个古老的文明遗迹。这是一座巨大的太空站,由高度发达的外星生物建造,他们似乎掌握了超越人类科技的力量。在遗迹中,艾登发现了一份父亲留下的日记,揭示了他的最后发现——这个文明正在面临一场生态危机,为了保护星球,他们选择了自我毁灭。 这个发现让艾登和他的团队陷入了沉思。他们意识到,如果人类继续贪婪地开发宇宙,也许会步上新绿洲文明的后尘。他们决定暂时留在新绿洲,用科技与智慧帮助那里的生物重建家园,同时警告全人类生态平衡的重要性。 在新绿洲的日子里,艾登和他的团队不仅学习了新的科技,也体验了生命的脆弱与坚韧。他们与新绿洲的生物建立了深厚的友谊,甚至开始尝试理解那些外星生物的语言,希望找到和平共存的方法。 最终,艾登以他的勇敢和智慧,向地球发出了关于新绿洲的警告,并提出了“星际和平”的理念。他的故事激励了全球,人类开始反思自己的行为,重新审视对宇宙的态度。 《星际遗产》的故事以艾登在新绿洲的最后一次演讲结束,他的话语回荡在宇宙中:“我们都是星际遗产 的一部分,每一个生命,每一片星域,都值得尊重和保护。让我们一起,为星际的和谐而努力。” real 4m45.451s user 0m56.169s sys 1m7.964s |
从上面结果来看,
总花费时间为:4:45
模型加载时间为4:17
28秒内生成了883个汉字,每秒大约31个汉字,速度比前面快10倍还多
7. 14B的 模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-14B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 40 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
time python test05-14B.py NUM_GPUS: 8 Loading checkpoint shards: 100%|███████████████| 8/8 [04:20<00:00, 32.62s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. 很抱歉,由于文本格式限制,我无法一次性提供一篇2万字的完整短篇科幻小说。但我可以帮你构思并给出一个大概的故事 框架和部分内容,你可以根据这个框架自行扩展。如果你需要简短的片段或故事大纲,以下是一个示例: 标题:《星际信使》 开头: 在遥远的未来,地球联盟的科学家们发现了一种新型能源——量子纠缠星尘,它能为星际旅行提供无限可能。主人公艾登·雷 诺兹,一名年轻的宇航员,被选中成为首批使用这种能源的星际信使。 正文: 1. 艾登接受任务,驾驶"星际号"飞船离开地球,目标是探索新发现的星系。他的任务是在宇宙中传递科学知识,促进文明 间的交流。 2. 在旅途中,艾登遭遇未知的外星生物——赛伦人,他们对地球文明充满好奇,但又因误解而敌视人类。艾登通过量子纠缠 星尘与地球进行即时通讯,请求援助。 3. 地球科学家利用星尘技术解读了赛伦人的语言,成功传达了和平的信息,避免了一场星际冲突。 4. 在接下来的旅程中,艾登见证了各种奇特的星球生态,学习了多元文明,同时也传播了人类的知识和价值观。 高潮: 艾登在一次意外中发现了一个被遗忘的遗迹,那是一个高度发达的古代文明,他们曾试图用星尘实现宇宙大一统,却因为过度依赖而导致种族衰落。艾登从中领悟到平衡和可持续发展的真谛。 结尾: 艾登带着这个教训回到地球,他向联盟提出关于星尘使用的谨慎建议,倡导人类在追求科技进步的同时,也要尊重自然、平衡发展。他的经历引发了全球的反思,星际信使计划也由此变得更加明智和人性化。 这个框架只是一个大概的构思,你可以根据自己的想象和创作添加细节,每个章节都可以进一步扩展,形成一部完整的2万 字短篇科幻小说。祝你写作顺利! real 10m45.922s user 7m3.979s sys 2m21.686s |
从上面结果来看,
总花费时间为:10:45
模型加载时间为4:20
6分钟内生成了724个汉字,每秒大约1.17个汉字,速度比较慢?
8. 14B 强制使用2张卡装载
单个24G的RTX 4090 无法装载14B的模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
from transformers import AutoModelForCausalLM, AutoTokenizer import torch MODEL_NAME = "Qwen/Qwen1.5-14B-Chat" # 定义一个函数来自动配置在多GPU环境下模型各部分的设备分布 def auto_configure_device_map(num_gpus: int): num_trans_layers = 40 # 定义Transformer模型的层数 per_gpu_layers = num_trans_layers / num_gpus # 计算每个GPU应承担的层数 # 初始化设备映射字典,指定一些特定模块应该放置的GPU编号 device_map = { 'model.embed_tokens': 0, # 嵌入层放在第一个GPU上 'model.norm': num_gpus-1, # 最后一个正则化层放在最后一个GPU上 'lm_head': 0 # 语言模型头(用于预测下一个词的层)放在最后一个GPU上 } # 将Transformer模型的每一层分配给一个GPU for i in range(num_trans_layers): device_map[f'model.layers.{i}'] = int(i//per_gpu_layers) return device_map # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 强制装载到2张卡里面 NUM_GPUS=2 # 如果有可用的GPU,则基于GPU数量自动配置设备映射;否则不使用设备映射 device_map = auto_configure_device_map(NUM_GPUS) if NUM_GPUS > 0 else None # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", device_map=device_map) # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() prompt = "写一个2万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=20000 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) |
运行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
time python test05-14B-2.py NUM_GPUS: 8 Loading checkpoint shards: 100%|████| 8/8 [07:34<00:00, 56.79s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. 很抱歉,由于文本长度限制,我无法在这里直接为您创作一篇完整的2万字短篇科幻小说。但我可以为您 提供一个故事大纲和部分开头,您可以根据这个大纲自行扩展或者邀请专业作家帮助您完成。以下是一个基本的框架: 标题:《星际编年史:时间裂缝》 故事大纲: 1. 开场:在不远的未来,人类成功实现了星际旅行,地球联合政府成立了星际探索队"曙光号"。主角, 年轻而富有才华的科学家艾伦·瑞恩被选中加入。 2. 发现:曙光号在一次探索中发现了一个神秘的时间裂缝,它连接着未知的维度。 3. 探索:艾伦带领团队深入裂缝,遭遇时间悖论和异次元生物,他们必须解开这些谜团以防止历史被改 变。 4. 冲突:在探索过程中,艾伦意外触发了时间连锁反应,他被困在过去,必须寻找回到现实的方法。 5. 内心成长:在过去的经历中,艾伦面对个人选择与责任的考验,他的信念和智慧成为他突破困境的关 键。 6. 转折点:艾伦通过与过去的自己交谈,意识到只有牺牲一部分记忆,才能修复时间线。 7. 结局:艾伦决定牺牲,成功回到现代,但失去了一些记忆。他分享了这次经历,引发了对时间、记忆 和宇宙真理的新思考。 开头(约1000字): 在2199年的地球联合政府星际探索基地,艾伦·瑞恩博士站在巨大的全息投影屏幕前,他的眼神专注而坚 定。作为“曙光号”星际探索队的一员,他即将带领团队启程,揭开宇宙的未知面纱。然而,他们此次的任务并非单纯的探索,而是寻找传说中的时间裂缝——一种能穿越时间和空间的神秘现象。 “曙光号”在宇宙中闪烁,像一颗璀璨的星辰划破黑暗。艾伦凝视着星图,心中充满了期待和紧张。他们即将面对的是未知的挑战,还是一个改变人类命运的机会?一切,只在一刹那间。 当他们的飞船穿越星系,一个前所未见的光晕突然出现,如同一道时空裂痕,引向一个充满谜团的领域。艾伦深吸一口气,他知道,他们已经踏上了这场史诗般的旅程的起点... 接下来的内容需要您根据这个大纲继续展开,构建情节,塑造角色,增加细节,让故事更加丰富和完整。祝您写作愉快! real 8m23.270s user 1m33.979s sys 2m6.338s |
从上面结果来看,
总花费时间为:8:23
模型加载时间为7:34
49秒内生成了877个汉字,每秒大约17个汉字,速度比前面快10倍
8.1. 14B 强制使用1张卡装载,8位量化
使用 1 张24G 装载,需要使用 BitsAndBytesConfig 进行8位量化,大约需要18G的GPU内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import torch import time MODEL_NAME = "Qwen/Qwen1.5-14B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float quantization_config = BitsAndBytesConfig(load_in_8bit=True) # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", quantization_config=quantization_config, device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个1万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=10000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") |
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
time python test05-14B-3.py NUM_GPUS: 8 Loading checkpoint shards: 100%|███████████| 8/8 [10:01<00:00, 75.17s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 604.6261560916901 seconds 很抱歉,由于文本格式限制,我无法一次性提供一篇一万字的完整短篇科幻小说。但我可以为你提供一个大概的故事框架和开头部分,你可以根据这个框架自行扩展或请专业作家进行创作。 标题:《星际编年史:时间裂痕》 --- 在遥远的未来,地球联盟的科学家们发现了一种名为"时空矩阵"的新技术,它能打开通往宇宙深处的时间通道。主角,年轻的物理学家艾登·哈特,是这项研究的关键成员,他渴望探索未知,破解宇宙的秘密。 --- 【第一章:启程】 艾登站在"时光号"飞船的指挥台上,心跳加速。他启动了时空矩阵,一道璀璨的光束划破夜空,他们被吸入了时间与空间的漩涡。穿越了几千年,他们降落在一颗陌生的星球——Zephyria,那里的文明正处在科技的黎明期。 --- 【第二章:异世界历险】 艾登伪装成Zephyrians的学者,开始调查他们的历史。然而,他意外地发现了一个关于时间裂痕的古老传说,这可能与他们文明的衰落有关。他决定寻找并修复这个裂痕,以防止灾难的发生。 --- 【第三章:危机四伏】 在寻找线索的过程中,艾登遭遇了各种危险,包括敌对势力的追捕和神秘力量的阻挠。他的团队成员逐一倒下,他独自面对挑战,内心充满了决心。 --- 【第四章:时间的抉择】 艾登在时间裂痕前做出了艰难的选择:牺牲自己关闭裂痕,保护整个宇宙的时间线,还是坚持回到地球,将这个秘密带回去改变人类的命运? --- 【尾声:归途与启示】 艾登选择关闭裂痕,但他并未消失,而是化为一道光,穿越时空回到了"时光号"。他带回的信息改变了地球联盟对时间旅行的理解,人类开始谨慎地对待时间,避免潜在的灾难。 --- 这个故事只是一个大纲,你可以根据需要添加更多的细节、角色发展和情节转折。希望对你有所帮助! Generated Tokens: 437 Tokens per second: 3.273142501998678 Total Generation Time: 133.51083850860596 seconds real 12m20.918s user 2m58.178s sys 1m54.848s |
8.2. 14B 强制使用1张卡装载,4位量化
使用 1 张24G 装载,需要使用 BitsAndBytesConfig 进行4位量化,大约需要10GB的GPU内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import torch import time MODEL_NAME = "Qwen/Qwen1.5-14B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float16 if NUM_GPUS > 0 else torch.float quantization_config = BitsAndBytesConfig(load_in_4bit=True) # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, attn_implementation="flash_attention_2", quantization_config=quantization_config, device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个1万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=10000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") |
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
time python test05-14B-4.py NUM_GPUS: 8 Loading checkpoint shards: 100%|███████| 8/8 [07:55<00:00, 59.49s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 479.92521357536316 seconds /home/tony/anaconda3/envs/Jamba/lib/python3.11/site-packages/bitsandbytes/nn/modules.py:391: UserWarning: Input type into Linear4bit is torch.float16, but bnb_4bit_compute_dtype=torch.float32 (default). This will lead to slow inference or training speed. warnings.warn('Input type into Linear4bit is torch.float16, but bnb_4bit_compute_dtype=torch.float32 (default). This will lead to slow inference or training speed.') 标题:星际穿越的遗产 在遥远的未来,地球已不再是人类的唯一家园。我们开拓了新的星系,建立了星际联邦,科技发展到了前所未有的高度。然而,在这个故事中,我们将聚焦在一个名叫"新希望星"的星球上,那里的居民们正在寻找一项神秘遗产,它可能改变他们整个文明的命运。 第一章:新希望星 新希望星,一颗位于银河边缘的宜居星球,其表面覆盖着繁茂的森林和神秘的遗迹。这里的居民,赛尔人,是一个拥有先进生物科技的种族,他们的城市隐藏在地下,以避免太阳辐射的侵扰。 第二章:遗产的传说 古老的传说中,赛尔人的祖先在星际旅行中发现了一项神秘的遗产,被称为“光谱之心”。这颗心形装置据说拥有无尽的知识和力量,能引领人类走向更高的文明阶段。然而,数百年来,没有任何人能找到它的踪迹。 第三章:失落的线索 一位名叫艾丽亚的年轻赛尔科学家,对这个传说充满了好奇。她决心找到“光谱之心”,希望能为她的星球带来和平与繁荣。她开始研究古代文献,寻找可能的线索。 第四章:冒险启程 艾丽亚组建了一个探险队,包括勇敢的飞行员瑞恩、智慧的工程师莉娜和一名神秘的外星盟友卡特。他们踏上了一场寻找“光谱之心”的旅程,穿越未知的星系,遭遇了各种危险。 第五章至第九章:星际挑战 他们在旅途中遭遇了外星生物的袭击,经历了黑洞边缘的险境,甚至在一次意外中发现了关于“光谱之心”的更深层信息。每一次挑战都让他们的友情更加深厚,也使他们更接近目标。 第十章:谜团揭晓 经过一系列艰难的探索,他们终于在一个古老的遗迹中找到了“光谱之心”。原来,这并非一件武器或力量源泉,而是一套教导智慧和道德伦理的课程。艾丽亚意识到,真正的遗产并非物质,而是理解和尊重宇宙万物的知识。 第十一章:新希望 他们带着这个新发现回到新希望星,分享了他们的发现。人们开始理解到,真正的进步并非来自于力量,而是来自内心的和谐与爱。赛尔人的社会开始发生深刻的变化,他们学会了共处,尊重差异,和平共生。 第十二章:尾声 艾丽亚成为了一个传奇,她的故事激励了新一代的赛尔人。他们不再追求物质的力量,而是追求心灵的成长和宇宙的理解。新希望星在“光谱之心”的影响下,成为了银河系的一颗璀璨明珠,象征着和平与智慧的光芒。 故事结束,但赛尔人的旅程并未停止,他们继续探索宇宙,寻找更多的知识和智慧,他们的故事在星际间流传,成为了一个永恒的传说。 Generated Tokens: 596 Tokens per second: 13.52436708752385 Total Generation Time: 44.06860566139221 seconds real 8m46.833s user 1m34.053s sys 1m49.504s |
前面有警告,我们去除警告,修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import torch import time MODEL_NAME = "Qwen/Qwen1.5-14B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float32 if NUM_GPUS > 0 else torch.float quantization_config = BitsAndBytesConfig(load_in_4bit=True) # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, quantization_config=quantization_config, device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个1万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=10000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
time python test05-14B-4.py NUM_GPUS: 8 Loading checkpoint shards: 100%|████████████| 8/8 [08:18<00:00, 62.30s/it] Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. Load Model Time: 501.56107807159424 seconds 标题:星际之谜:光年之外的遗产 在遥远的未来,地球已经成为了人类文明的摇篮。科技的发展使得人类探索宇宙的步伐日益加快,星际旅行变得寻常。我们的主人公,年轻的天文学家艾米丽·哈特,是一个对未知充满好奇的探险者,她被选中 加入了一项名为“光年计划”的太空探索任务。 故事开始: 第一章:启程的号角 艾米丽站在巨大的星际飞船“希望号”上,望着那颗蓝色星球渐行渐远。她的任务是前往最近发现的一颗名为“伊甸星”的神秘星球,寻找可能存在的外星文明遗迹。船员们紧张而兴奋,每个人都明白这是一次改变历史的冒险。 第二章:未知的伊甸星 经过数月的旅行,希望号抵达了伊甸星。艾米丽带领团队着陆,他们发现了一个被古老能量护盾保护的遗迹,这让她想起传说中的“星际遗产”。 第三章:遗产的秘密 艾米丽和团队深入遗迹,发现了一系列高科技设备,其中一台神秘的“时间共鸣器”引起了他们的注意。他们意识到,这个遗产可能与时间旅行有关。 第四章:时间的试炼 艾米丽决定激活时间共鸣器,试图穿越时间以了解更多关于伊甸星文明的信息。然而,每一次尝试都引发了一连串的时空混乱,他们陷入了无法预知的危险。 第五章:时空迷宫 在混乱中,艾米丽意外地回到了过去,遇见了年轻的自己。她们联手解开了一道道谜题,揭示了伊甸星文明的真相——他们曾试图阻止一场毁灭性的灾难,但失败了。 第六章:使命与抉择 艾米丽意识到,只有阻止这场灾难,才能修复时空,回到现实。她决定牺牲自己,将年轻的自己送回过去,拯救伊甸星。 第七章:光年的决断 艾米丽在最后关头,启动了时间共鸣器,将自己的意识与过去的自己融合。一道耀眼的光芒闪过,她消失在了时间的长河中。 尾声:永恒的遗产 当艾米丽重新睁开眼睛,发现自己回到了希望号上,伊甸星的灾难已被阻止。她的牺牲拯救了两个世界,她的名字被镌刻在星际历史的篇章中。虽然她失去了肉身,但她的精神和遗产永远留在了光年之外的星海。 艾米丽的故事告诉我们,勇敢面对未知,坚守正义,即使付出生命的代价,也能创造奇迹。她用生命编织出的传奇,将激励后世的探险者继续探索宇宙的奥秘。 Generated Tokens: 557 Tokens per second: 15.294492646068159 Total Generation Time: 36.41833782196045 seconds real 9m0.806s user 1m31.212s sys 1m57.739s |
8.3. 保存 14B 4位量化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import torch import time MODEL_NAME = "Qwen/Qwen1.5-14B-Chat" # 检测可用的GPU数量 NUM_GPUS = torch.cuda.device_count() print(f"NUM_GPUS: {NUM_GPUS}") # 如果有可用的GPU,则使用第一个GPU;否则使用CPU device = torch.device("cuda") if NUM_GPUS > 0 else torch.device("cpu") # 根据是否使用GPU设置数据类型(半精度或全精度) device_dtype = torch.float32 if NUM_GPUS > 0 else torch.float quantization_config = BitsAndBytesConfig(load_in_4bit=True) # 获取起始时间戳 start_time = time.time() model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, trust_remote_code=True, torch_dtype=device_dtype, quantization_config=quantization_config, device_map="cuda:0") # 加载分词器和模型,指定设备映射和数据类型 tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = model.eval() end_time = time.time() elapsed_time = end_time - start_time print(f"Load Model Time: {elapsed_time} seconds") start_time2 = time.time() prompt = "写一个1万字的有头有尾的短篇科幻小说." messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) model_inputs = tokenizer([text], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=10000 ) end_time2 = time.time() elapsed_time2 = end_time2 - start_time2 elapsed_time = end_time2 - start_time num_tokens_generated = len(generated_ids[0]) - len(model_inputs.input_ids[0]) tokens_per_second = num_tokens_generated / elapsed_time2 generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print(response) print(f"Generated Tokens: {num_tokens_generated}") print(f"Tokens per second: {tokens_per_second}") print(f"Total Generation Time: {elapsed_time2} seconds") print(f"config.save_pretrained") model.config.save_pretrained('Qwen/Qwen1.5-14B-Chat-Int4') print(f"model.save_pretrained") model.save_pretrained('Qwen/Qwen1.5-14B-Chat-Int4') print(f"tokenizer.save_pretrained") |