Open fdwr opened 5 months ago
Reading those three issues it seems like upgrading to double
or long long
would get you most of the way? With JS you should have ~int53 or some such, which is way more than what you are clamping at currently. It doesn't give you precision beyond that, but it's not immediately clear from the issues whether that's needed.
Howdy Anne. We're looking at a union of (double and BigInt)
, where double
(float64) is large enough to handle any floating point constant (float16, float32, float64), and BigInt
is large enough to handle any integer constant (int8, uint8, int32, uint32, int64, uint64). Are you suggesting a union of (double or long long)
?
Using only double gets us most of the way, yes, but it's the endpoints that concern me. We want JS to be able to accurately map the full range of int64/uint64 tensors (e.g. numpy.uint64
, tensorflow.uint64
, ONNX.TensorProto.DataType.UINT64
, BNNSDataTypeUInt64
, MPSDataType.uInt64
, mx.uint64
, ov::element::Type_t::u64
...), and yeah, most values past 2^52 likely don't need exact precision, but for cases like sentinel values and masks (e.g. 0xFFFFFFFFFFFFFFFF
), we'd have a challenge representing them via a double. You would think that passing a really large double like 1.8446744073709552e+19 might map cleanly to 0xFFFFFFFFFFFFFFFF
, but you get varying results depending on the FPU logic. Even with C++ on my x64 machine, if you attempt to static_cast
a double like 1.8446744073709552e+19 to uint64_t
, you get back a surprising answer of 0x8000000000000000
instead of 0xFFFFFFFFFFFFFFFF
, and I don't know what happens on ARM/M1.
For long long
(https://webidl.spec.whatwg.org/#idl-long-long), is BigInt
the way to express int64/uint64 via JS? Thanks.
No, neither double
nor long long
would give you int64 precision. It seems really strange to overload a double with an integer though. Seems like it should be (long long or BigInt)
then.
Seems like it should be (long long or BigInt) then.
The WebNN user calls a function to apply an operation on a multidimensional tensor (e.g. fill a constant, fill a sequence, pad with a constant value) or to create a multidimensional tensor, where those tensors can be of various data types (including float64/int64/uint64/...), and the caller passes a scalar parameter to that function call which should be able to represent any of the target tensor's potential values. Using BigInt
or long long
would just introduce the opposite problem, as integer types cannot express float64 point precision (3.4 would be truncated to 3).
The current definition @miaobin has prototyped for a constant sequence fill is:
MLOperand constant(MLOperandDescriptor desc, (double or bigint) start, (double or bigint) step);
Sorry for being slow, that seems reasonable.
FYI @inexorabletash, Anne says it seems reasonable :).
What is the issue with the Web IDL Standard?
Opening an issue per the wording here: https://webidl.spec.whatwg.org/#limit-bigint-numeric-unions
We have 3 use cases in WebNN where we need to be able to accept full precision from the API and retain it passed all the way down to the bottom, because float64 cannot express the full precision of int64 (and conversely, an int64 could not express the full precision of a float64).
Evidently it's murky territory, as Bin Miao hit a bug in the Chromium implementation "We met the problem of using the keyword
or
in IDL to create a union type containing double and bigint. In the generated file 'v8_union_bigint_double.cc', it was only judged that the incoming data was of JS number type and there is no judgment that it is BigInt, which causes an error to be reported when BigInt data is passed in when calling this API using JS code.", and Joshua notes that "Use of bigint is extremely limited in Chromium at the moment, so I'm not surprised if the binding code generation can't handle a union with it yet ... this may just be the first spec".FYI @inexorabletash, @annevk, @honry, @miaobin