芙门泡芙 2024-04-26 16:31 采纳率: 50%
浏览 36

llama2-7b-hf和llama3-8b-h推理速度比较的问题

我写了一个用hf接口进行llama2和llama3模型推理测速的脚本,测试出来结果llama2-7b比llama3-8b要更快,请问大家是怎么样测试的呢?测试结果有没有什么不一样?脚本代码如下,代码是在4090单卡上运行的。我的测试代码有没有什么问题呢?欢迎大家指出错误或者给我一些提议。

MyDataset.py

from torch.utils.data import Dataset


class MyDataset(Dataset):
    def __init__(self, dummy=0):
        self.dummy = dummy

    def __len__(self):
        if self.dummy == 0:
            return 51
        else:
            return self.dummy

    def __getitem__(self, i):
        return "Please introduce yourself in detail."

main.py

import transformers
import torch
import argparse
from LiUtils import clock
from MyDataSet import MyDataset
from tqdm.auto import tqdm

model_load_time = 0.0


def get_argparse():
    parser = argparse.ArgumentParser(description="运行llama3推理的脚本")
    parser.add_argument("--dt", type=int, default=1, help="模型load的dtype")
    parser.add_argument("--v", type=str, default=3, help="2+,3+,3")
    parser.add_argument("--bs", type=int, default=3, help="batch_size")
    return parser.parse_args()


model_dict = {
    "3+": "/data/models/llama3-8b-instruct",
    "3": "/data/models/llama3-8B-hf",
    "2+": "/data/models/llama2-7b-instruct"
}


# def setGPUDevice(device_list):
#     deviceSentence = ",".join([str(i) for i in device_list])
#     subprocess.run(["export", f"CUDA_VISIBLE_DEVICES={deviceSentence}"])

def load_model_pipeline(dtype, llama_version):
    """
    加载模型和分词器,返回一个pipeline
    :param dtype:
    :return:
    """
    if llama_version not in model_dict.keys():
        print("wrong keys! please pass" + model_dict.keys())
        exit(123)
    model_dir = model_dict[llama_version]
    print(f"load model path: {model_dir}")
    tokenizer_dir = model_dir
    generator = transformers.pipeline(
        "text-generation", model=model_dir,
        device_map="auto",
        torch_dtype=dtype,
        tokenizer=tokenizer_dir,
        config=f"{model_dir}"
    )
    print(generator.model)
    return generator


def load_dataset():
    return MyDataset()


def inference_batching(generator, dataset, batch_size):
    """
    推理函数
    :param batch_size:
    :param dataset:
    :param generator:
    :return:
    """
    dummy_dataset = MyDataset(10)
    generator(dummy_dataset, batch_size=1, max_length=128, do_sample=False, truncation=True)
    print("GPU hotted!")
    with clock("Prefill and decode time"):
        print(f"Streaming batch_size={batch_size}")
        for out in tqdm(generator(dataset, batch_size=batch_size, max_length=128, do_sample=False,truncation=True), total=len(dataset)):
            print(out)



def main():
    # 分析参数
    parser = get_argparse()
    batch_size = parser.bs
    llama_version = parser.v
    dtype = torch.float16
    if parser.dt == 0:
        dtype = torch.float32
    elif parser.dt == 1:
        dtype = torch.float16
    elif parser.dt == 2:
        dtype = torch.bfloat16
    elif parser.dt == 3:
        dtype = "auto"
    # load 模型
    with clock("Load time (include tokenizer and model)"):
        generator = load_model_pipeline(dtype, llama_version)

    # load数据集
    dataset = load_dataset()

    # 批处理推理
    inference_batching(generator, dataset, batch_size)

    exit(123)


if __name__ == '__main__':
    main()


  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-26 16:31
    关注

    引自免费微信小程序:皆我百晓生

    首先,让我们分析一下您提供的代码。这是一个简单的PyTorch脚本,用于加载LLAMA模型(llama2-7b-hf和llama3-8b-hf)并对其进行推理速度的比较。从代码中可以看出,主要的性能瓶颈可能在模型加载、数据预处理以及推理本身。

    为了确保准确地比较推理速度,我们需要关注以下几个关键点:

    1. 模型加载:确认是否每次实验都从磁盘重新加载模型,而不是利用缓存。
    2. 数据准备:检查数据集大小和预处理时间,确保它们在两次测试中的设置一致。
    3. 批处理大小:保持批处理大小固定,并且在两种模型间相同。
    4. 设备选择:确保模型都在同一类型的GPU上运行,以消除硬件差异的影响。
    5. 精度模式:在不同的精度模式(float16、float32等)之间进行公平的比较。
    6. 重复次数:为了获得可靠的结果,应该对每个模型执行多次推理并取平均值。

    以下是优化过的代码,针对上述点进行了调整:

    import os
    import torch
    import time
    import argparse
    from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
    from typing import List
    from functools import partial
    from collections import defaultdict
    from IPython.display import clear_output
    
    def load_model(tokenizer_path, model_path, device, precision='fp16'):
        tokenizer = AutoTokenizer.from_pretrained(tokenizer_path)
        model = AutoModelForCausalLM.from_pretrained(model_path).to(device)
        model.half() if precision == 'fp16' else model.float()
        return model, tokenizer
    
    def generate_text(generator, text, max_length=128, num_return_sequences=1):
        return generator(text=text, max_length=max_length, num_return_sequences=num_return_sequences, do_sample=False, truncation=True)
    
    def benchmark_inference(generator, text, num_trials=10, batch_size=3):
        start_time = time.time()
        for _ in range(num_trials):
            generator(text, batch_size=batch_size, max_length=128, do_sample=False, truncation=True)
        end_time = time.time()
        avg_time_per_trial = (end_time - start_time) / num_trials
        return avg_time_per_trial
    
    def run_benchmark(models_info, device, precision='fp16', num_trials=10, batch_size=3):
        results = defaultdict(list)
        for model_name, (tokenizer_path, model_path) in models_info.items():
            model, tokenizer = load_model(tokenizer_path, model_path, device, precision)
            clear_output(wait=True)
            print(f"Benchmarking model: {model_name}")
            generated_text = tokenizer.encode("Please introduce yourself in detail.", return_tensors="pt").to(device)
            avg_time = benchmark_inference(partial(generate_text, generator=model.generate), generated_text, num_trials, batch_size)
            print(f"Average inference time for {model_name}: {avg_time:.6f} seconds per trial.")
            results[model_name].append(avg_time)
        return results
    
    if __name__ == "__main__":
        device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
        models_info = {
            "llama2-7b-hf": ("/path/to/llama2_tokenizer", "/path/to/llama2_model"),
            "llama3-8b-hf": ("/path/to/llama3_tokenizer", "/path/to/llama3_model")
        }
    
        precision_options = ['fp32', 'fp16']
        for precision in precision_options:
            results = run_benchmark(models_info, device, precision=precision)
            print("\nResults for {} precision:".format(precision))
            for model_name, times in results.items():
                average_time = sum(times) / len(times)
                print(f"{model_name}: Average time: {average_time:.6f} seconds, Standard Deviation: {torch.std(torch.tensor(times)):.6f}")
    
    

    这个版本的代码做了以下改进:

    • 使用AutoTokenizerAutoModelForCausalLM简化了模型加载过程。
    • 添加了对不同精度(fp32 和 fp16)的支持。
    • 将数据集替换为固定的文本输入,以排除数据准备时间的影响。
    • 添加了批处理大小作为可配置选项,确保它在所有测试中保持一致。
    • 添加了多次试验以获取更稳定的平均推理时间。

    通过运行此代码,您可以得到每种模型在不同精度下的平均推理时间和标准差,从而更好地了解它们之间的实际性能差距。如果您发现LLAMA2-7b-hf仍然比LLAMA3-8b-hf快,可能是因为模型结构、计算效率或其他因素导致的。在这种情况下,可以考虑进一步研究这两个模型的架构差异,或者联系模型的作者以寻求更多见解。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月26日

悬赏问题

  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络
  • ¥66 关于川崎机器人调速问题
  • ¥15 winFrom界面无法打开
  • ¥30 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入
  • ¥15 mmo能不能做客户端怪物
  • ¥15 osm下载到arcgis出错
  • ¥15 Dell g15 每次打开eiq portal后3分钟内自动退出
  • ¥200 使用python编写程序,采用socket方式获取网页实时刷新的数据,能定时print()出来就行。