gte embedding模型compile后的模型推理有问题
收藏回复举报
gte embedding模型compile后的模型推理有问题
t('forum.solved') 已解决
新人帖
发表于2025-02-15 14:40:59
0 查看

问题主要是

1. 同样的输入两次推理的输出有一定概率不一样,而且相差还挺大

2. npu的输出和cpu的输出有差异(这个先解决了上面问题1再说)

重现步骤

1. 使用下面脚本蒋gte模型compile。这里有个注意点是不能直接用AutoModel来装入模型,否则编译的时候会出现有变量引用找不到的问题。实验之后我发现把模型的代码从/root/.cache/huggingface/modules/transformers_modules/Alibaba-NLP/new-impl/40ced75c3017eb27626c9d4ea981bde21a2662f4/*.py拷贝到./ , 然后修改modeling.py, 将其中的 "from .configuration import NewConfig" 改成 "from configuration import NewConfig",最后程序就能compile成功了

import time
import torch
import mindietorch
import numpy as np
from transformers import AutoTokenizer
import sys
import os
import random
os.environ['TOKENIZERS_PARALLELISM'] = 'true'

# run this first:
# 1. cp /root/.cache/huggingface/modules/transformers_modules/Alibaba-NLP/new-impl/40ced75c3017eb27626c9d4ea981bde21a2662f4/*.py ./
# 2. modify modeling.py, change "from .configuration import NewConfig" to "from configuration import NewConfig"
from modeling import NewModel

max_length = 512

# 初始化数组
string_array = []

# 生成字符串数组
current_length = 256
while current_length <= max_length:
    string_array.append("啊" * current_length)
    current_length *= 2

# 随机排序
random.shuffle(string_array)

MODEL_PATH = "/llm/Alibaba-NLP/gte-multilingual-base/"
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True, local_files_only=True)
#model = AutoModel.from_pretrained(MODEL_PATH, trust_remote_code=True)
model = NewModel.from_pretrained(MODEL_PATH, trust_remote_code=True)
model.to(torch.float32).eval()

inputs = tokenizer(string_array, add_special_tokens=True, padding='max_length', max_length=max_length, truncation=True, return_tensors='pt').to("cpu")

# 调用torch.jit.trace生成traced_model
#input_ids = inputs['input_ids']
#attention_mask = inputs['attention_mask']
input_ids = torch.ones((1,max_length), dtype=torch.int)
attention_mask = torch.ones((1,max_length), dtype=torch.int)
traced_model = torch.jit.trace(model, [input_ids, attention_mask], strict=False)
#traced_model = torch.jit.script(model)
traced_model.to(torch.float32).eval().to("npu")

# 把traced_model转化成npu模型
#torch.jit.save(traced_model, 'gte_multilingual_base_traced.pt')

# 编译成HW模型
#min_shape = (1, 1)
#max_shape = (len(string_array), max_length)  # batch, max length
#inputs = []
#inputs.append(mindietorch.Input(min_shape = min_shape, max_shape = max_shape, dtype=input_ids.dtype))
#inputs.append(mindietorch.Input(min_shape = min_shape, max_shape = max_shape, dtype=attention_mask.dtype))
inputs = [mindietorch.Input((1, max_length),dtype=input_ids.dtype), mindietorch.Input((1,max_length), dtype=attention_mask.dtype)]

#loaded_model = loaded_model.eval().to("npu")
compiled_module = mindietorch.compile(
     traced_model,
     inputs=inputs,
     #precision_policy=mindietorch.PrecisionPolicy.FP16,
     #truncate_long_and_double=True,
     truncate_long_and_double=False,
     require_full_compilation=False,
     allow_tensor_replace_int=False,
     min_block_size=3,
     torch_executed_ops=[],
     optimization_level=0,
     soc_version="Ascend310P3",
)

# ts模型保存
compiled_module.save("CompiledModel.ts")

mindietorch.finalize()

保存好模型后,用下面的脚本测试

import json
import time
import torch
import mindietorch
import numpy as np
from transformers import AutoModel, AutoTokenizer
import sys
from modeling import NewModel
import os
import random
import torch.nn.functional as F

os.environ['TOKENIZERS_PARALLELISM'] = 'true'
torch.manual_seed(88)

max_length = 512

MODEL_PATH = "/llm/Alibaba-NLP/gte-multilingual-base/"
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True, local_files_only=True)

cpu_model = NewModel.from_pretrained(MODEL_PATH)
cpu_model.eval()

compiled_model = torch.jit.load("CompiledModel.ts")
mindietorch.set_device(0)
compiled_model.to(torch.float32).eval().to("npu")
modeloutput = compiled_model(torch.ones((1,max_length), dtype=torch.int).to("npu"), torch.ones((1,max_length), dtype=torch.int).to("npu"))

text = "阿斯蒂芬啊倒萨方发阿发暗暗大师傅奥奥福德阿凡达噶双方的安抚"
for i in range(8192):
    # 生成一个[1,max_length]长度的随机字符串
    random_length = random.randint(1, max_length)
    random_string = ''.join(random.choice(text) for _ in range(random_length))
    #print(random_string)
    inputs = tokenizer(random_string, add_special_tokens=True, padding='max_length', max_length=max_length, truncation=True, return_tensors='pt').to("cpu")
    input_ids = inputs['input_ids'].to(dtype=torch.int)
    attention_mask = inputs['attention_mask'].to(dtype=torch.int)

    # cpu计算
    modeloutput = cpu_model(input_ids, attention_mask)
    cpu_embedding = modeloutput.last_hidden_state[:, 0][:768].detach().cpu()
    pooler_cpu = modeloutput.get('pooler_output', None)
    hidden_states_cpu = modeloutput.get('hidden_states', None)
    attentions_cpu = modeloutput.get('attentions',None)

    # npu计算第一次
    modeloutput = compiled_model(input_ids.to("npu", dtype=torch.int), attention_mask.to("npu", dtype=torch.int))
    npu_embedding1 = modeloutput['last_hidden_state'][:, 0][:768].detach().to(torch.float32).cpu()
    pooler_output1 = modeloutput.get('pooler_output', None)
    hidden_states1 = modeloutput.get('hidden_states', None)
    attentions1 = modeloutput.get('attentions',None)

    # npu计算第二次
    modeloutput = compiled_model(input_ids.to("npu", dtype=torch.int), attention_mask.to("npu", dtype=torch.int))
    npu_embedding2 = modeloutput['last_hidden_state'][:, 0][:768].detach().to(torch.float32).cpu()
    pooler_output2 = modeloutput.get('pooler_output', None)
    hidden_states2 = modeloutput.get('hidden_states', None)
    attentions2 = modeloutput.get('attentions', None)
    #pooler_output2 = pooler_output1
    #hidden_states2 = hidden_states1
    #attentions2 = attentions1

    cosine_similarity = F.cosine_similarity(npu_embedding1, npu_embedding2).item()
    if cosine_similarity>0.999:
        print("*", end='', flush=True)
        continue
    else:
        print("tensor cos:", cosine_similarity, flush=True)

    if pooler_output1 is None and pooler_output2 is None:
        print("tensor pooler_output is None")
    else:
        pooler_output1 = pooler_output1.detach().cpu()
        pooler_output2 = pooler_output2.detach().cpu()
        print("tensor 0 type:", pooler_cpu.dtype, ",", pooler_output1.dtype)
        #print("[0]cpu:", pooler_cpu.shape, ":", pooler_cpu[0:8])
        #print("[0]1:", pooler_output1.shape, ":", pooler_output1[0:8])
        #print("[0]2:", pooler_output2.shape, ":", pooler_output2[0:8])
        if not torch.equal(pooler_output1, pooler_cpu):
            #print("[0]cpu:", pooler_cpu.shape, ":", pooler_cpu.dtype, ":", pooler_cpu)
            print("[0]1:", pooler_output1.dtype, ":", pooler_output1)
            print("[0]2:", pooler_output2.dtype, ":", pooler_output2)
            print("tensor not match")

    if hidden_states1 is None and hidden_states2 is None:
        print("hidden_states is None")
    else:
        hidden_states1 = hidden_states1.detach().cpu()
        hidden_states2 = hidden_states2.detach().cpu()
        print("tensor 1 type:", hidden_states_cpu.dtype, ":", hidden_states1.dtype)
        #print("[1]cpu:", hidden_states_cpu.shape, ":", hidden_states_cpu[0:8])
        #print("[1]1:", hidden_states1.shape, ":", hidden_states1[0:8])
        #print("[1]2:", hidden_states2.shape, ":", hidden_states2[0:8])
        if not torch.equal(hidden_states1, hidden_states_cpu):
            #print("[1]cpu:", hidden_states_cpu.shape, ":", hidden_states_cpu.dtype, ":", hidden_states_cpu)
            print("[1]1:", hidden_states1.dtype, ":", hidden_states1)
            print("[1]2:", hidden_states2.dtype, ":", hidden_states2)
            print("tensor not match")

    if attentions1 is None and attentions2 is None:
        print("attentions is None")
    else:
        attentions1 = attentions1.detach().cpu()
        attentions2 = attentions2.detach().cpu()
        #print("[2]cpu:", attentions_cpu.shape, ":", attentions_cpu)
        #print("[2]1:", attentions1.shape, ":", attentions1)
        #print("[2]2:", attentions2.shape, ":", attentions2)
        print("tensor 2 type:", attentions_cpu, ":", attentions1.dtype)
        if not torch.equal(attentions1, attentions_cpu):
            #print("[2]cpu:", attentions_cpu.shape, ":", attentions_cpu.dtype, ":", attentions_cpu)
            print("[2]1:", attentions1.dtype, ":", attentions1)
            print("[2]2:", attentions2.dtype, ":", attentions2[..., -1])
            print("tensor not match")

    #if torch.equal(npu_embedding1, npu_embedding2):
    #    print(".", end="", flush=True)
    #else:
    #    print(npu_embedding1[0])
    #    print(npu_embedding2[0], flush=True)

mindietorch.finalize()

这里最奇怪的是同样的input, 两次npu计算的结果有一定的概率是不一样的

我的测试环境是docker, 镜像是swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:1.0.RC3-300I-Duo-arm64

本帖最后由 匿名用户 于 2025/09/27 17:35:49 编辑

我要发帖子