Closed
[Documentation|文档反馈]: aclnnLinalgCholesky 资料 self/out 数据类型漏列 FLOAT16(实现已支持) #3957
liuhanwen8Add on 13 days agoClosed at 9 days ago
13 days ago Added label: documentation
陈思
12 days ago Comments:
12 days ago Comments:
您好,感谢反馈!已核对提交 584b2ea6,参数表的 self 和 out 均只列 FLOAT、BFLOAT16;而A2 对应的支持列表已包含 FLOAT16,参数检查也要求 out 与 self 类型一致。因此,本单 FLOAT16 输入/输出的资料描述与实现存在缺项。
计算路径会将 FLOAT16、BFLOAT16 输入转为 FLOAT 后执行 Cholesky,再转回 out 类型。这与您提供的 FLOAT16 成功执行及量化误差现象相符,本次未新增硬件复测。建议在确认支持的产品范围内同时补齐两列 FLOAT16,并说明内部 FP32 计算与输出类型恢复;其他产品限制应单独准确标注,不能由本次 A2 用例扩大支持范围。后续将继续跟踪类型清单、产品说明与实现的一致性核对。


12 days ago Assign chen_0715 as responsible person
12 days ago Added label: pending-confirmation
12 days ago Removed label: pending-confirmation
11 days ago Assign Nice_try as responsible person
10 days ago Associated pull request
9 days ago Close issue
9 days ago Added label: resolved
一、文档链接 (必填)
https://gitcode.com/cann/ops-math/blob/master/math/cholesky/docs/aclnnLinalgCholesky.md
二、问题文档片段 (必填)
现象
资料的 self/out 数据类型限定为
FLOAT、BFLOAT16;实现的支持列表包含DT_FLOAT16(math/cholesky/op_api/aclnn_linalg_cholesky.cpp:34),并在:157对BF16/FLOAT16统一 Cast 到FLOAT后计算。实测 fp16 两段返回 0/0、sync 0,分解结果与 fp32 一致(在 fp16 量化误差内);真正不支持的 INT32 返回 161002,说明 dtype 校验本身生效。:85/:105FLOAT、BFLOAT16(无 FLOAT16):34/:157DT_FLOAT16在支持列表内,且走 Cast 分支期望
self 与 out 的「数据类型」列补
FLOAT16;若个别产品不支持,按资料既有写法在产品支持情况中单独注明,而不是从公共 dtype 列表里省略。环境
cann/ops-mathmaster584b2ea6cbaeba684a51a74296d82d4d50ab3b0f(git fetch后 local == origin/master)A=[[10,2,3],[2,8,1],[3,1,6]],upper=false复现步骤
repro.sh。export ASCEND_HOME_PATH=<CANN 安装目录>(需含include/aclnnop与lib64)。bash repro.sh(脚本编译repro.cpp并依次跑 fp32 / fp16 / int32)。fp16 first=0 second=0 sync=0 L00=3.162109 ...,即资料未列出的 FLOAT16 正常执行。int32 first=161002:不支持的 dtype 仍被拦下,排除「dtype 校验整体失效」。复现脚本
#!/bin/bash # aclnnLinalgCholesky dtype probe: doc lists FLOAT/BFLOAT16, does FLOAT16 really pass? set -e CANN=${ASCEND_HOME_PATH:-/usr/local/Ascend/ascend-toolkit/latest} export ASCEND_OPP_PATH=${ASCEND_OPP_PATH:-$CANN/opp} export LD_LIBRARY_PATH=$CANN/lib64:/usr/local/Ascend/driver/lib64:$LD_LIBRARY_PATH export ASCEND_RT_VISIBLE_DEVICES=${DEV:-5} cat > repro.cpp <<'CPP' // build: g++ -std=c++17 -O2 repro.cpp -o repro -I$CANN/include -I$CANN/include/aclnnop -L$CANN/lib64 -Wl,--allow-shlib-undefined -lascendcl -lopapi -lnnopbase // 对照组 fp32(资料列出);缺陷组 fp16(资料未列出);负向对照 int32(真不支持,应 161002) #include <bits/stdc++.h> #include "acl/acl.h" #include "aclnnop/aclnn_linalg_cholesky.h" struct T { void* d = nullptr; aclTensor* t = nullptr; }; static const int N = 3; static const float A[N][N] = {{10,2,3},{2,8,1},{3,1,6}}; static bool Mk(const void* h, size_t bytes, aclDataType dt, std::vector<int64_t> s, T& o) { if (aclrtMalloc(&o.d, bytes, ACL_MEM_MALLOC_HUGE_FIRST) || aclrtMemcpy(o.d, bytes, h, bytes, ACL_MEMCPY_HOST_TO_DEVICE)) return false; std::vector<int64_t> st(s.size(), 1); for (int i = (int)s.size() - 2; i >= 0; --i) st[i] = s[i + 1] * st[i + 1]; o.t = aclCreateTensor(s.data(), s.size(), dt, st.data(), 0, ACL_FORMAT_ND, s.data(), s.size(), o.d); return o.t != nullptr; } static void Run(const char* name, aclDataType dt, const void* in, size_t bytes) { T a, o; std::vector<char> out(bytes, 0); if (!Mk(in, bytes, dt, {N, N}, a) || !Mk(out.data(), bytes, dt, {N, N}, o)) return; uint64_t ws = 0; aclOpExecutor* ex = nullptr; aclnnStatus r1 = aclnnLinalgCholeskyGetWorkspaceSize(a.t, false, o.t, &ws, &ex); void* wsa = nullptr; if (r1 == 0 && ws > 0) aclrtMalloc(&wsa, ws, ACL_MEM_MALLOC_HUGE_FIRST); aclnnStatus r2 = r1 == 0 ? aclnnLinalgCholesky(wsa, ws, ex, nullptr) : r1; aclnnStatus r3 = aclrtSynchronizeStream(nullptr); aclrtMemcpy(out.data(), bytes, o.d, bytes, ACL_MEMCPY_DEVICE_TO_HOST); if (r1 != 0) { printf("%-6s first=%d second=%d (dtype outside support list)\n", name, r1, r2); } else { double L[N][N] = {{0}}, err = 0; for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) L[i][j] = dt == ACL_FLOAT ? ((float*)out.data())[i*N+j] : (double)((__fp16*)out.data())[i*N+j]; for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) { double s = 0; for (int k = 0; k < N; ++k) s += L[i][k] * L[j][k]; err = std::max(err, std::fabs(s - A[i][j])); } printf("%-6s first=%d second=%d sync=%d L00=%.6f max|LLt-A|=%.1e\n", name, r1, r2, r3, L[0][0], err); } aclDestroyTensor(a.t); aclDestroyTensor(o.t); aclrtFree(a.d); aclrtFree(o.d); if (wsa) aclrtFree(wsa); } int main() { if (aclInit(nullptr) != ACL_SUCCESS || aclrtSetDevice(0) != ACL_SUCCESS) return 3; __fp16 A16[N][N]; int32_t A32[N][N]; for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) { A16[i][j] = A[i][j]; A32[i][j] = 1; } Run("fp32", ACL_FLOAT, A, sizeof(A)); Run("fp16", ACL_FLOAT16, A16, sizeof(A16)); Run("int32", ACL_INT32, A32, sizeof(A32)); aclrtResetDevice(0); aclFinalize(); return 0; } CPP g++ -std=c++17 -O2 repro.cpp -o repro -I$CANN/include -I$CANN/include/aclnnop \ -L$CANN/lib64 -Wl,--allow-shlib-undefined -lascendcl -lopapi -lnnopbase ./repro实测输出(5 号卡):
影响
按资料选型的调用方会把 fp16 排除在 aclnnLinalgCholesky 之外,先 Cast 到 fp32 或 bf16 再调用,多一次显存往返与一次 kernel;实际实现已支持 fp16 并给出正确分解。
建议
资料 self/out 数据类型补
FLOAT16。与 #3944(Bernoulli 的 selfRef 漏列 BFLOAT16)属同类但接口不同:本条是 aclnnLinalgCholesky 的 self/out 漏列 FLOAT16,且已有实测两段 0 + 正确分解。