Double precision support in C++ AMP

C++ AMP supports various data types for usage in the restrict(amp) functions that you schedule on the accelerator. One of those types is double. There are caveats and extra information that you need to know with regards to double precision and this post aims to help you with that.

It all depends on your driver

Not all hardware supports doubles so if you have double precision requirements, you need to check that your hardware has such support.

In addition, you must ensure you have the latest driver for your hardware (by visiting the hardware vendor’s website) that enables the support – it is not an uncommon pitfall to read online the specs for your hardware saying one thing, but finding that your installed driver reports another thing because it hasn’t been updated.

To complicate matters further, there are two levels of double support and hence there are two APIs exposed by C++ AMP to let you query for that support.

Limited double precision

In Windows Display Driver Model (WDDM) 1.1, double precision is an optional feature for hardware vendors to implement in their DirectX drivers. Even if they do, it is what we call limited double precision support. That means that the following double operations are not supported:

  • FMA (fused multiply add).
  • Division
  • Reciprocal (rcp)
  • Casting between int and double

Through C++ AMP you’ll know whether your system has a WDDM 1.1 driver that supports limited double precision by checking the supports_limited_double_precision property on the accelerator, e.g.

bool can_use_doubles_with_limits = accelerator().supports_limited_double_precision;

(Full) Double precision

In WDDM 1.2 (currently supported by Windows 8 and Windows Server 2012 only), the limitations above were removed. So while double precision is still an optional feature, when hardware vendors opt in to implementing it, you get full (aka extended) double precision support.

Through C++ AMP you’ll know your system has a WDDM 1.2 driver that opted in to supporting double precision by checking the supports_double_precision property on the accelerator, e.g.

bool can_use_doubles = accelerator().supports_double_precision;

Note that full double precision is required by the concurrency::precise_math functions in <amp_math.h>

C++ AMP runtime exception

As you know, calls to the C++ AMP API on the host can throw exceptions that I encourage you to learn more about at our blog post on C++ AMP Exceptions.

If you try to use doubles on a card where the driver does not support doubles at all, or the driver has limited double precision support and you try something unsupported such as division, you will get a concurrency::runtime_exception with one of the following messages

“concurrency::parallel_for_each uses features (full double_precision) unsupported by the selected accelerator.”

“concurrency::parallel_for_each uses features (limited_double_precision) unsupported by the selected accelerator.”

Whichever message you get, if you are running under the debug configuration, it also includes the following text:

“ID3D11Device::CreateComputeShader: Shader uses features not recognized by this D3D version.”

Comments (9)

  1. How do you find out which is the code-line which uses a double-precision feature? I get the exception … but I know my code doesn't use any double-code at all (no double-variables, no double-constants etc.).

  2. Hi Ethatron,

    The most common I have seen are double constants like "float x = 0.0" the "0.0" is actually a double that is converted to float. The second most common is including precise_math. Any math function from that namespace even if only for single-precision overload would require double precision support:…/math-library-for-c-amp.aspx

    If none of the above help, then try to comment out portions of the code to track it down… we will look into improving diagnosability for this scenario, thanks for posting a question!



  3. Ethatron,

    Another option would be to look for double precision intructions (dadd, dmul, ddiv, deq, dge, dlt, dmov, dmax, dmin, dfma, itod, dtoi, ftod, dtof, drcp) in the C++ AMP  kernel disassembly in the VS2012 GPU debugger.

    If you can find one, you should be able to find the corresponding source line by running to the specific instruction.


  4. Don McCrady says:

    A third option would be to compile with /W4.  Hopefully that will generate a warning when the double gets trunctated back to float.

  5. IS MS thinking of adding another form of restrict that will give you compile time errors if you use doubles in a way that won't work on a card with only limited double support. Reading through instructions output by the compiler seems like a bold leap back to the 70s.

  6. Thanks for the feedback. We will take your suggestion into consideration.

  7. Rolf Huisman says:

    Can't warp be extended or an emulation be made so that amp always supports doubles. Currently my video card doesn't support it so I can't test or deploy double. For my customers I would need to make two versions or not use doubles at all.

  8. Thanks for the feedback Rolf. We realize the importance of this and are working on it.

  9. cendyyao says:


    I am interesting about using the C++AMP.

    Is there some samples about how to use the functions such modf(float x, float * iptr) and other functions   in the amp?