-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: MultiplyAddEstimate #98053
Comments
Tagging subscribers to this area: @dotnet/area-system-numerics Issue DetailsSummaryToday users have access to the direct operators As such, it is proposed we provide an explicit API Proposalnamespace System
{
public partial struct Double
{
public static double MultiplyAddEstimate(double x, double y, double addend);
}
public partial struct Half
{
public static Half MultiplyAddEstimate(Half x, Half y, Half addend);
}
public partial struct Single
{
public static float MultiplyAddEstimate(float x, float y, float addend);
}
}
namespace System.Numerics
{
public partial interface IFloatingPointIeee754<TSelf>
{
static virtual TSelf MultiplyAddEstimate(TSelf x, TSelf y, TSelf addend);
}
public partial class Vector
{
static Vector<double> MultiplyAddEstimate(Vector<double> x, Vector<double> y, Vector<double> addend);
static Vector<float> MultiplyAddEstimate(Vector<float> x, Vector<float> y, Vector<float> addend);
}
}
namespace System.Numerics.Tensors
{
public partial class TensorPrimitives
{
public static void MultiplyAddEstimate<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, ReadOnlySpan<T> addend, Span<T> destination) where T : IFloatingPointIeee754<T>;
}
}
namespace System.Runtime.InteropServices
{
public partial struct NFloat
{
public static NFloat MultiplyAddEstimate(NFloat x, NFloat y, NFloat addend);
}
}
namespace System.Runtime.Intrinsics
{
public partial class Vector64
{
static Vector64<double> MultiplyAddEstimate(Vector64<double> x, Vector64<double> y, Vector64<double> addend);
static Vector64<float> MultiplyAddEstimate(Vector64<float> x, Vector64<float> y, Vector64<float> addend);
}
public partial class Vector128
{
static Vector128<double> MultiplyAddEstimate(Vector128<double> x, Vector128<double> y, Vector128<double> addend);
static Vector128<float> MultiplyAddEstimate(Vector128<float> x, Vector128<float> y, Vector128<float> addend);
}
public partial class Vector256
{
static Vector256<double> MultiplyAddEstimate(Vector256<double> x, Vector256<double> y, Vector256<double> addend);
static Vector256<float> MultiplyAddEstimate(Vector256<float> x, Vector256<float> y, Vector256<float> addend);
}
public partial class Vector512
{
static Vector512<double> MultiplyAddEstimate(Vector512<double> x, Vector512<double> y, Vector512<double> addend);
static Vector512<float> MultiplyAddEstimate(Vector512<float> x, Vector512<float> y, Vector512<float> addend);
}
}
|
Looks good as proposed. For anyone who wants to hear Jeremy be way too nerdy about linguistics, you need to listen to the API Review video, because Estimate and Estimate are different words. namespace System
{
public partial struct Double
{
public static double MultiplyAddEstimate(double x, double y, double addend);
}
public partial struct Half
{
public static Half MultiplyAddEstimate(Half x, Half y, Half addend);
}
public partial struct Single
{
public static float MultiplyAddEstimate(float x, float y, float addend);
}
}
namespace System.Numerics
{
public partial interface IFloatingPointIeee754<TSelf>
{
static virtual TSelf MultiplyAddEstimate(TSelf x, TSelf y, TSelf addend);
}
public partial class Vector
{
static Vector<double> MultiplyAddEstimate(Vector<double> x, Vector<double> y, Vector<double> addend);
static Vector<float> MultiplyAddEstimate(Vector<float> x, Vector<float> y, Vector<float> addend);
}
}
namespace System.Numerics.Tensors
{
public partial class TensorPrimitives
{
public static void MultiplyAddEstimate<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, ReadOnlySpan<T> addend, Span<T> destination) where T : IFloatingPointIeee754<T>;
}
}
namespace System.Runtime.InteropServices
{
public partial struct NFloat
{
public static NFloat MultiplyAddEstimate(NFloat x, NFloat y, NFloat addend);
}
}
namespace System.Runtime.Intrinsics
{
public partial class Vector64
{
static Vector64<double> MultiplyAddEstimate(Vector64<double> x, Vector64<double> y, Vector64<double> addend);
static Vector64<float> MultiplyAddEstimate(Vector64<float> x, Vector64<float> y, Vector64<float> addend);
}
public partial class Vector128
{
static Vector128<double> MultiplyAddEstimate(Vector128<double> x, Vector128<double> y, Vector128<double> addend);
static Vector128<float> MultiplyAddEstimate(Vector128<float> x, Vector128<float> y, Vector128<float> addend);
}
public partial class Vector256
{
static Vector256<double> MultiplyAddEstimate(Vector256<double> x, Vector256<double> y, Vector256<double> addend);
static Vector256<float> MultiplyAddEstimate(Vector256<float> x, Vector256<float> y, Vector256<float> addend);
}
public partial class Vector512
{
static Vector512<double> MultiplyAddEstimate(Vector512<double> x, Vector512<double> y, Vector512<double> addend);
static Vector512<float> MultiplyAddEstimate(Vector512<float> x, Vector512<float> y, Vector512<float> addend);
}
} |
any chance of adding same functions to Vec2/3/4 as convenience? like i suggested here a while ago #87377 (originally my proposal was for |
As is, dev's aren't blocked from the APIs as they can simply |
Just FYI, I'm adding the TensorPrimitives APIs as part of fixing the FusedMultiplyAdd APIs. |
This comment was marked as resolved.
This comment was marked as resolved.
|
I missed reading that. Sorry about that. |
By the way, should I also include |
For explicit consistency, yes. |
I wonder why can’t jitter automatically use this function instead of requiring to specify it explicitly. |
Because it isn't safe. Some native compilers offer a feature switch such as When it comes to non-deterministic features like this, the best practice is to require the user to opt-in at a per call site basis. This minimizes the risk and helps ensure that it's only done where it would actually be beneficial and the user understands the impact of what they're opting into. |
Summary
Today users have access to the direct operators
(x * y) + z
and the fused named methodFusedMultiplyAdd(x, y, z)
. On some hardware using one over the other can provide significant perf advantages, however not all hardware provides acceleration forfma
and further due to the difference in result (which may be1 ULP
difference for any standalone operation), it is not something that the runtime can freely optimize to use.As such, it is proposed we provide an explicit
Estimate
function (matching the convention we've used for other operation where the result can differ across machines but the operation is not itself unsafe) that will implicitly pick the "best" of the two operations. Users who want a specific behavior can still get it by using the direct functions and users who want to opt-in can.API Proposal
The text was updated successfully, but these errors were encountered: