编程模型和语言层

通过在 Intel XPU 上执行矩阵乘法,展示了如何使用 PyTorch 和 Intel 扩展库进行计算,并记录了执行时间和输出结果。

  • 使用 torch.rand 创建两个 1000x1000 的随机矩阵 A 和 B,并将它们分配到指定的设备(即 XPU)。
  • 使用 time.time() 记录开始时间。执行矩阵乘法 C = torch.mm(A, B),计算矩阵 A 和 B 的乘积,并将结果存储在矩阵 C 中。记录结束时间。
  • 输出矩阵乘法的结果 C。输出结果矩阵 C 的第一个元素 C[0, 0].item(),使用 .item() 将张量的标量值提取为 Python 数值。计算并输出执行时间,格式化为小数点后六位。
import torch
import intel_extension_for_pytorch as ipex
import time

# 设置设备为 Intel XPU
device = 'xpu'
print(device)
# 创建两个随机矩阵
A = torch.rand(1000, 1000, device=device)
B = torch.rand(1000, 1000, device=device)


start_time = time.time()
C = torch.mm(A, B)  # 矩阵乘法
end_time = time.time()

# 输出结果和执行时间
print("矩阵乘法结果:", C)
print("矩阵乘法结果的第一个元素:", C[0, 0].item())
print("执行时间: {:.6f}秒".format(end_time - start_time))

结果

xpu
矩阵乘法结果: tensor([[246.4091, 255.5069, 252.2399,  ..., 247.3566, 251.4520, 261.5430],
        [252.0482, 253.8953, 248.0201,  ..., 246.2549, 249.1073, 261.2542],
        [244.2107, 255.6172, 245.4884,  ..., 245.6505, 246.0593, 252.1882],
        ...,
        [242.1431, 245.1475, 241.2979,  ..., 246.3311, 243.1896, 253.1462],
        [245.9689, 248.1380, 245.4601,  ..., 245.5615, 247.0750, 255.7415],
        [237.5993, 248.8701, 236.9447,  ..., 238.5728, 240.6091, 247.0459]],
       device='xpu:0')
矩阵乘法结果的第一个元素: 246.4091339111328
执行时间: 0.072625秒

在 Intel XPU 上实现矩阵加法和减法的示例代码

  • 记录加法开始时间。使用 C_add = A + B 计算矩阵加法。记录加法结束时间。
  • 记录减法开始时间。使用 C_sub = A - B 计算矩阵减法。记录减法结束时间。
import torch
import intel_extension_for_pytorch as ipex
import time

# 设置设备为 Intel XPU
device = 'xpu'

# 创建两个随机矩阵
A = torch.rand(1000, 1000, device=device)
B = torch.rand(1000, 1000, device=device)

# 矩阵加法
start_time_add = time.time()
C_add = A + B  # 矩阵加法
end_time_add = time.time()

# 矩阵减法
start_time_sub = time.time()
C_sub = A - B  # 矩阵减法
end_time_sub = time.time()

# 输出结果和执行时间
print("矩阵加法结果的第一个元素:", C_add[0, 0].item())
print("矩阵加法执行时间: {:.6f}秒".format(end_time_add - start_time_add))

print("矩阵减法结果的第一个元素:", C_sub[0, 0].item())
print("矩阵减法执行时间: {:.6f}秒".format(end_time_sub - start_time_sub))

结果

矩阵加法结果的第一个元素: 1.158061146736145
矩阵加法执行时间: 0.004714秒
矩阵减法结果的第一个元素: -0.2508704960346222
矩阵减法执行时间: 0.000067秒

代码展示了如何在 Intel XPU 上优化和运行一个预训练的 ResNet50 模型,适合进行快速推理测试。

  • 加载预训练的 ResNet50 模型,并设置为评估模式。创建一个随机输入数据 data,其形状为 (1, 3, 224, 224),对应于一张 224x224 的 RGB 图像。
  • 将模型和输入数据移动到 Intel XPU 上。使用 ipex.optimize(model) 优化模型,以提高性能。
  • 在不计算梯度的情况下执行模型推理,以节省内存和计算资源。输出执行结束的提示。
import torch
import torchvision.models as models

############# code changes ###############
import intel_extension_for_pytorch as ipex

############# code changes ###############

model = models.resnet50(weights="ResNet50_Weights.DEFAULT")
model.eval()
data = torch.rand(1, 3, 224, 224)

######## code changes #######
model = model.to("xpu")
data = data.to("xpu")
model = ipex.optimize(model)
######## code changes #######

with torch.no_grad():
    model(data)

print("Execution finished")

结果

Execution finished

使用英特尔的 PyTorch 扩展(IPEX)对一个预训练的 ResNet-50 模型进行静态量化,并通过校准数据优化模型的性能,最终将量化后的模型保存为文件。这样处理后的模型在推理时会更高效,占用的存储空间也会减少。

  • intel_extension_for_pytorch: 提供针对英特尔硬件的 PyTorch 模型优化。prepare 和 convert: 准备模型以进行量化和将模型转换为量化格式的函数。torchvision.models: 包含像 ResNet 这样的预训练模型。torchvision: 包含数据集和数据预处理转换。
  • 使用 model.eval() 将模型切换到评估模式,禁用丢弃层和批量归一化层。创建一个形状为 (128, 3, 224, 224) 的随机张量 data,用于示例输入。
  • 使用 ipex.quantization.default_static_qconfig_mapping 获取默认的静态量化配置映射。代码中提供了一个示例,展示如何自定义量化配置(注释部分)。
  • 调用 prepare 函数为量化准备模型,指定量化配置映射和示例输入。inplace=False 表示不在原地修改模型。
  • 使用 torchvision.transforms 进行数据预处理,包括调整大小、转换为张量和归一化。创建数据集并通过 DataLoader 加载,用于后续的模型校准。
  • 在无梯度计算的上下文中,遍历数据加载器进行模型校准。对每个批次的数据调用准备好的模型,以进行量化校准。
  • 调用 convert 函数将准备好的模型转换为量化模型。使用 torch.jit.trace 跟踪转换后的模型,以便生成一个可优化的 TorchScript 模型。使用 torch.jit.freeze 冻结模型,进一步优化其性能。
import torchvision

DOWNLOAD = True
DATA = "/tmp/datasets/cifar10/"

transform = torchvision.transforms.Compose(
    [
        torchvision.transforms.Resize((224, 224)),
        torchvision.transforms.ToTensor(),
        torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
    ]
)
train_dataset = torchvision.datasets.CIFAR10(
    root=DATA,
    train=True,
    transform=transform,
    download=DOWNLOAD,
)
calibration_data_loader = torch.utils.data.DataLoader(
    dataset=train_dataset, batch_size=512
)

with torch.no_grad():
    for batch_idx, (d, target) in enumerate(calibration_data_loader):
        print(f"calibrated on batch {batch_idx} out of {len(calibration_data_loader)}")
        prepared_model(d)
##############################  # noqa F401

converted_model = convert(prepared_model)
with torch.no_grad():
    traced_model = torch.jit.trace(converted_model, data)
    traced_model = torch.jit.freeze(traced_model)

traced_model.save("static_quantized_model.pt")

print("Saved model to: static_quantized_model.pt")

结果

calibrated on batch 0 out of 98
calibrated on batch 1 out of 98
calibrated on batch 2 out of 98
...
calibrated on batch 96 out of 98
calibrated on batch 97 out of 98
calibrated on batch 98 out of 98
Saved model to: static_quantized_model.pt