defweight_dequant(x: torch.Tensor, s: torch.Tensor, block_size:int=128)-> torch.Tensor:"""
Dequantizes the given weight tensor using the provided scale tensor.
Args:
x (torch.Tensor): The quantized weight tensor of shape (M, N).
s (torch.Tensor): The scale tensor of shape (M, N).
block_size (int, optional): The block size to use for dequantization. Defaults to 128.
Returns:
torch.Tensor: The dequantized weight tensor of the same shape as `x`.
Raises:
AssertionError: If `x` or `s` are not contiguous or if their dimensions are not 2.
"""assert x.is_contiguous()and s.is_contiguous(),'Input tensors must be contiguous'# 确保输入张量是连续的(即内存布局连续)assert x.dim()==2and s.dim()==2,'Input tensors must have 2 dimensions'# 确保输入张量 x 和 s 都是二维的
M, N = x.size()# 获取输入张量 x 的尺寸 M (行数) 和 N (列数)# 创建一个和 x 形状相同的新张量 y,用来保存反量化后的结果
y = torch.empty_like(x, dtype=torch.get_default_dtype())# 定义一个 grid 函数来计算 triton 内核所需的网格大小# triton.cdiv 是向上取整除法,用来确保我们分配足够的线程处理每个块
grid =lambda meta:(triton.cdiv(M, meta['BLOCK_SIZE']), triton.cdiv(N, meta['BLOCK_SIZE']))# 调用 triton 内核 `weight_dequant_kernel` 进行反量化操作# 将 quantized weight `x` 和 scale `s` 与结果张量 `y` 一起传递给内核# `M`, `N`, `block_size` 作为额外的参数传递
weight_dequant_kernel[grid](x, s, y, M, N, BLOCK_SIZE=block_size)# 返回反量化后的张量 yreturn y
计算网格大小:
grid = lambda meta: (triton.cdiv(M, meta['BLOCK_SIZE']), triton.cdiv(N, meta['BLOCK_SIZE'])): 使用 triton.cdiv 来计算块的数量。triton.cdiv 是向上取整除法,用于确定每个维度需要多少个块来处理 M 和 N 大小的数据。meta['BLOCK_SIZE']) 是每个块处理的元素数量(默认值为 128)。
weight_dequant_kernel
Nvidia GPU CUDA使用grid、block、thread进行索引。
实现反量化的核函数(模型可能使用的是LSQ(Learned Step Quantization)Quantization,仅有量化步长参数),通过weight_dequant_kernel[grid](x, s, y, M, N, BLOCK_SIZE=block_size)调用:
@triton.jit# 使用 Triton 编译器将此函数编译为高效的 GPU 内核defweight_dequant_kernel(x_ptr, s_ptr, y_ptr, M, N, BLOCK_SIZE: tl.constexpr):"""
Dequantizes weights using the provided scaling factors and stores the result.
Args:
x_ptr (tl.pointer): Pointer to the quantized weights.
s_ptr (tl.pointer): Pointer to the scaling factors.
y_ptr (tl.pointer): Pointer to the output buffer for dequantized weights.
M (int): Number of rows in the weight matrix.
N (int): Number of columns in the weight matrix.
BLOCK_SIZE (tl.constexpr): Size of the block for tiling.
Returns:
None
"""# 获取当前线程在程序中的编号
pid_m = tl.program_id(axis=0)# 获取当前行维度上的线程编号,pid_m 和 pid_n 的范围由矩阵的尺寸 M 和 N,以及线程块的大小 BLOCK_SIZE 决定
pid_n = tl.program_id(axis=1)# 获取当前列维度上的线程编号,pid_m 的值从 0 到 ceil(M / BLOCK_SIZE) - 1# 计算矩阵列的块数
n = tl.cdiv(N, BLOCK_SIZE)# 使用向上取整除法计算列方向上的块数# 计算当前线程块在行和列方向上的偏移量
offs_m = pid_m * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)# 当前块在行方向的偏移量
offs_n = pid_n * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)# 当前块在列方向的偏移量# 将行和列的偏移量组合成一个二维的索引数组
offs = offs_m[:,None]* N + offs_n[None,:]# 将行和列偏移量结合,得到每个元素的全局索引,offs_m[:, None]形状会变成 (BLOCK_SIZE, 1),相加广播后变为(BLOCK_SIZE, BLOCK_SIZE)# 使用掩码保证我们不会超出矩阵的边界
mask =(offs_m[:,None]< M)&(offs_n[None,:]< N)# 掩码,确保线程不会访问超出矩阵范围的数据# 加载量化后的权重数据(量化后的值)
x = tl.load(x_ptr + offs, mask=mask).to(tl.float32)# 从内存中加载量化后的数据,并转换为 float32 类型# 加载缩放因子
s = tl.load(s_ptr + pid_m * n + pid_n)# 从内存中加载对应的缩放因子,s_ptr是指向缩放因子数组的指针,pid_m * n + pid_n计算出当前线程块在缩放因子数组中的位置。# 执行去量化操作:去量化 = 量化值 * 缩放因子
y = x * s # 去量化的计算公式# 将去量化后的数据存储到输出缓存中
tl.store(y_ptr + offs, y, mask=mask)# 将去量化后的值存储到输出内存中,使用掩码确保数据存储在合法的范围内,`offs` 是索引,`mask=mask` 确保只有合法的元素被存储
作者:来自 Elastic Mark Hoy Elasticsearch 开放推理 API 现已支持 Azure AI Studio。在此博客中了解如何将 Azure AI Studio 功能与 Elasticsearch 结合使用。 作为我们持续致力于为 Microsoft Azure 开发人员提供他们选择的工具的一部分,我们很高兴地宣…
命令格式如
psql -U user -d db 或者 sudo psql -U user -d db
修改配置
/etc/postgresql/16/main/postgresql.conf 改成md5,然后重新启动pgsql
sudo systemctl restart postgresql
快速入门
1.第一份代码
先检查自己是否有正确下载 Go,如果没有直接去 Go 安装 进行安装。
# 检查是否有 Go
$ go version
go version go1.23.4 linux/amd64然后根据 Go 的入门教程 开始进行学习。
# 初始化 Go 项目
$ mkdir example && cd example # Go…