一、结论
用半精度加载的模型不要用CPU推理,因为CPU可能不支持FP16指令集,即便支持也会导致性能下降或者不兼容的问题
二、问题
模型加载:
GPT2ForSequenceClassification.from_pretrained(model_path, torch_dtype=torch.float16).to('cpu')
模型推理:
inputs = self.tokenizer(text=texts, return_tensors="pt", padding='longest',truncation=True,max_length=512).to(self._device)
logits = self.model(**inputs).logits
报错如下:
RuntimeError: “LayerNormKernelImpl” not implemented for ‘Half’
三、根因定位
改成如下:
self.model.to(torch.float32)
logits = self.model(**inputs).logits
推理就正常了,说明是16精度的问题
为什么16精度不能在CPU上运行呢?
半精度浮点格式(FP16)是一种使用16位(而不是传统的32位,即FP32)来表示浮点数的格式。它通常用于深度学习模型,因为它可以减少模型的内存占用,并可能在支持FP16计算的GPU上加速模型的训练和推理。
然而,并不是所有的CPU都原生支持FP16计算。相对于GPU,CPU在处理FP16计算方面通常要缓慢得多,因为它们可能需要将这些数值转换回FP32来进行计算,然后再转换回FP16来存储。这样的转换不仅增加了计算负担,还可能导致性能下降。
另一方面,GPU,尤其是NVIDIA的一些较新的GPU,如支持Tensor Cores的V100、A100等,专门设计了硬件加速FP16运算,这使得它们在处理这种数据类型时非常高效。这就是为什么半精度模型经常在GPU上使用,而不是CPU。
此外,如果你尝试在不支持FP16指令集的CPU上执行FP16模型,你可能会遇到错误或性能问题。这是因为CPU需要模拟FP16运算,这通常是通过软件在FP32的帮助下完成的,效率较低。
如果你希望在CPU上进行推理,通常需要将模型转换回FP32精度。在PyTorch中,这可以通过调用.to(torch.float32)或.float()来实现;
model.to(torch.float32)
# 或者
model.float()
CPU推理一定要用单精度