You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动张量化数据时如何创建自定义TensorFloat16Bit?

如何正确创建并填充TensorFloat16Bit以适配FP16 ONNX模型?

我来帮你解决这个TensorFloat16Bit的绑定问题——核心原因是你没处理好FP16数据的字节长度和格式转换,下面是具体的修改方案:

首先理清问题根源:

  • TensorFloat16Bit的每个元素是2字节的FP16格式(对应uint16_t),而原来的TensorFloat是4字节的32位float,所以它的buffer容量正好是前者的一半。你之前直接用float*去访问,必然会越界触发访问违规。
  • ITensorNative::GetBuffer确实只支持返回BYTE**或uint8_t**,所以需要先拿到字节指针,再转换成uint16_t*来操作FP16数据。

接下来是修改后的完整代码,我会标注关键改动点:

#include <cstdint>
// 推荐用DirectXMath提供的成熟FP16转换函数
#include <DirectXMath.h>
using namespace DirectX;

// 若无法使用DirectXMath,可替换为其他可靠的float转FP16实现
uint16_t float_to_half(float f) {
    return XMConvertFloatToHalf(f);
}

// ... 你的其他业务代码 ...

std::vector<int64_t> shape = { 1, channels, height , width };
uint16_t* pFP16Tensor = nullptr;
uint32_t uCapacity;

// 1. 创建TensorFloat16Bit代替原TensorFloat
TensorFloat16Bit tf16 = TensorFloat16Bit::Create(shape);
com_ptr<ITensorNative> itn = tf16.as<ITensorNative>();
CHECK_HRESULT(itn->GetBuffer(reinterpret_cast<BYTE**>(&pFP16Tensor), &uCapacity));

// 2. 转换BGRA数据到FP16格式的BGR张量(丢弃Alpha通道)
if (BitmapPixelFormat::Bgra8 == pixelFormat)
{
    const uint32_t pixelCount = height * width;
    for (UINT32 i = 0; i < size; i += 4)
    {
        UINT32 pixelInd = i / 4;
        // 先将0-255像素值归一化到0-1的float范围(模型通常期望归一化输入)
        float b_val = static_cast<float>(pData[i]) / 255.0f;
        float g_val = static_cast<float>(pData[i+1]) / 255.0f;
        float r_val = static_cast<float>(pData[i+2]) / 255.0f;

        // 填充对应通道的FP16编码数据
        pFP16Tensor[pixelInd] = float_to_half(b_val);
        pFP16Tensor[pixelCount + pixelInd] = float_to_half(g_val);
        pFP16Tensor[pixelCount * 2 + pixelInd] = float_to_half(r_val);
    }
}

关键改动说明:

  1. Tensor类型替换:用TensorFloat16Bit::Create(shape)创建FP16张量,形状保持不变(形状描述的是维度数量,不是字节数)。
  2. 指针类型转换:把GetBuffer返回的BYTE*直接转换成uint16_t*,因为FP16元素占2字节,这样可以直接按元素索引访问,避免字节偏移计算错误。
  3. 数据格式转换:
    • 补上了0-255到0-1的归一化步骤(你原代码遗漏了这一步,模型推理通常需要归一化后的输入)。
    • 用成熟的工具函数将32位float转换成16位FP16编码值,避免手动转换引入的精度问题。
  4. 索引逻辑兼容:通道的索引计算和原代码一致,因为我们是按元素数而非字节数索引,无需调整偏移倍数。

最后提醒:确保你的硬件支持FP16推理(比如支持DirectML的GPU),否则即使创建了FP16张量,模型可能还是会 fallback 到FP32,无法获得预期的性能提升。

内容的提问来源于stack exchange,提问作者Anna Maule

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:25:13