lessCode.net
Delicious
Saturday
Jan172015

64-bit Numerical Stability with Visual C++ 2013 on FMA3-capable Haswell Chips (_set_FMA3_enable)

An interesting diversion this week, when we noticed regression tests failing on our TeamCity build server. The differences were mostly tiny, but warranted a closer inspection since there were no significant code changes to explain them, and the tests were still passing on most developer PCs. The only thing that had really changed was that we’d moved the TeamCity build agents to newer hardware (with later-model Haswell chipsets).

We were able to boil the differences in behaviour down to a simple 3-line C++ program (essentially a call to std::exp), and, sure enough, the program gave a different result when compiled in VS2013 and executed on the new Haswell CPU. Any other combination of C++ runtime and chip (and any x86 build) gave us our “expected” answer. Obviously you can’t have your build server and your developer PCs disagree when it comes to floating-point calculations without chaos (or games of baseline whack-a-mole between developers when some of them are running newer PCs than others).

We tried forcing the rounding mode with _controlfp_s, but just ended up with different differences. We tried the Intel C++ compiler (which was slightly more stable but still off between Haswell and older CPUs).

As it turns out, the VC++ 2013 runtime uses FMA3 instructions for some transcendental functions (std::exp included), when available at runtime, and this was the difference for us. After disabling this behaviour in the runtime with _set_FMA3_enable(0), our tests started passing on both types of CPU, with no other code or baseline changes necessary.

Thanks to James McNellis for pointing us in the right direction on the FMA3 optimizations.

James also noted that the FMA3 optimizations are much faster, so at some point we will experiment with enabling those, and update our baselines, but for now we can move on with stable numbers between builds.

Thursday
Aug222013

Bug? Content-Based Correlation in Windows Workflow Foundation

This one caused me quite a bit of grief this week – maybe I can save someone else some pain. When configuring content-based correlation in the Workflow (4.0/4.5) designer, I think there’s a subtle bug in the dialog that allows you to choose the correlation key and XPath expression used to establish correlation on a Receive or SendReply activity.

image

It manifests itself when the workflow engine attempts to apply the correlation query at runtime:

A correlation query yielded an empty result set. Please ensure correlation queries for the endpoint are correctly configured.

 

It only occurs under the following conditions:

  • The message or parameter that contains the correlation is a complex DataContract (i.e. not a primitive value type).
  • That DataContract type is derived from another base class DataContract.
  • The correlation property comes from the base class.
  • The base class DataContract and the derived class DataContract are in different namespaces.

 

Under these conditions, the Add Correlation Initializers dialog sets the namespace of the property as being defined in the namespace of the derived class, not the base class.

Fortunately the fix is easy – you can manually edit the XAML to refer to the namespace of the base class instead, e.g:

<XPathMessageQuery x:Key="key1">
<XPathMessageQuery.Namespaces>
 <ssx:XPathMessageContextMarkup>
    <x:String x:Key="xg0">http://schemas.datacontract.org/2004/07/ClassLibrary2</x:String>
    <x:String x:Key="xgSc">http://tempuri.org/</x:String>
 </ssx:XPathMessageContextMarkup>
</XPathMessageQuery.Namespaces>sm:body()/xgSc:StartResponse/xgSc:StartResult/xg0:Id</XPathMessageQuery>
Monday
Mar252013

Did Verisign revoke their own certificate?

image

Wednesday
Mar132013

Google is shutting down Reader

http://googleblog.blogspot.com/2013/03/a-second-spring-of-cleaning.html

Wait, what? This is Google’s best product, and they’re shit-canning it?

This has to rank up there with Fox’s decision to cancel Firefly

Friday
Feb012013

What’s My Super Bowl Pool Box Worth?

A bit of fun for this Super Bowl weekend. If you’re unfamiliar with a Super Bowl pool, the basics are simple:

Draw a 10 x 10 grid. One axis represents the AFC team, the other represents the NFC team. Participants pay a fixed amount for each of the 100 boxes. A payoff is set for each quarter of the game. Each row of the grid is randomly assigned a digit from 0-9, and likewise for each column of the grid. At the end of each quarter of the game, the final digit of each team’s score is used to determine the winning box for that quarter, and the owner of that box gets the loot.

The interesting question for box owners after the box numbers are assigned is: How much am I likely to win with these numbers? Moreover, if you’d entered the same pool every year since the Super Bowl began (ie. a pool with the same per-quarter payoffs), and happened to get the same numbers every year, how much would you have won in total? Obviously this is a contrived scenario, but an analysis of the history of Super Bowl scores makes for some interesting observations.

The nature of the scoring system in American Football is obviously the biggest factor in determining the “value” of a box: 3 (field goal) & 7 (touchdown + extra point), and their multiples, 6, 9, 4 and 1 seem likely to be winners. Also, the person who owns the 0-0 box stands to potentially win the entire pot before a ball is kicked or thrown, if two lousy offenses can’t score, or if the scoring goes in sets of touchdown, extra point, field goal. But if you think you have good numbers, a safety or a missed extra point are likely to ruin your day.

So, how much is my box worth in the above scenario?

// Per-quarter points scored for every superbowl - AFC,NFC
let quarterPoints = [
    ([ 0;10; 0; 0],[ 7; 7;14; 7]);
    ([ 0; 7; 0; 7],[ 3;13;10; 7]);
    ([ 0; 7; 6; 3],[ 0; 0; 0; 7]);
    ([ 3;13; 7; 0],[ 0; 0; 7; 0]);
    ([ 0; 6; 0;10],[ 3;10; 0; 0]);
    ([ 0; 3; 0; 0],[ 3; 7; 7; 7]);
    ([ 7; 7; 0; 0],[ 0; 0; 0; 7]);
    ([14; 3; 7; 0],[ 0; 0; 0; 7]);
    ([ 0; 2; 7; 7],[ 0; 0; 0; 6]);
    ([ 7; 0; 0;14],[ 7; 3; 0; 7]);
    ([ 0;16; 3;13],[ 0; 0; 7; 7]);
    ([ 0; 0;10; 0],[10; 3; 7; 7]);
    ([ 7;14; 0;14],[ 7; 7; 3;14]);
    ([ 3; 7; 7;14],[ 7; 6; 6; 0]);
    ([14; 0;10; 3],[ 0; 3; 0; 7]);
    ([ 0; 0; 7;14],[ 7;13; 0; 6]);
    ([ 7;10; 0; 0],[ 0;10; 3;14]);
    ([ 7;14;14; 3],[ 0; 3; 6; 0]);
    ([10; 6; 0; 0],[ 7;21;10; 0]);
    ([ 3; 0; 0; 7],[13;10;21; 2]);
    ([10; 0; 0;10],[ 7; 2;17;13]);
    ([10; 0; 0; 0],[ 0;35; 0; 7]);
    ([ 0; 3;10; 3],[ 3; 0; 3;14]);
    ([ 3; 0; 7; 0],[13;14;14;14]);
    ([ 3; 9; 0; 7],[ 3; 7; 7; 3]);
    ([ 0; 0;10;14],[ 0;17;14; 6]);
    ([ 7; 3; 7; 0],[14;14; 3;21]);
    ([ 3;10; 0; 0],[ 6; 0;14;10]);
    ([ 7; 3; 8; 8],[14;14;14; 7]);
    ([ 0; 7; 0;10],[10; 3; 7; 7]);
    ([14; 0; 7; 0],[10;17; 8; 0]);
    ([ 7;10; 7; 7],[ 7; 7; 3; 7]);
    ([ 7;10; 0;17],[ 3; 3; 0;13]);
    ([ 0; 0; 6;10],[ 3; 6; 7; 7]);
    ([ 7; 3;14;10],[ 0; 0; 7; 0]);
    ([ 0;14; 3; 3],[ 3; 0; 0;14]);
    ([ 3; 0; 6;12],[ 3;17;14;14]);
    ([ 0;14; 0;18],[ 0;10; 0;19]);
    ([ 0; 7; 7;10],[ 0; 7; 7; 7]);
    ([ 0; 7; 7; 7],[ 3; 0; 7; 0]);
    ([ 6;10; 6; 7],[14; 0; 3; 0]);
    ([ 0; 7; 0; 7],[ 3; 0; 0;14]);
    ([ 3;14; 3; 7],[ 0; 7; 0;16]);
    ([10; 0; 7; 0],[ 0; 6;10;15]);
    ([ 0;10; 7; 8],[14; 7; 0;10]);
    ([ 9; 0; 6; 6],[ 0;10; 7; 0]) ]

// Dollars to win at the end of each quarter
let prizes = [| 50; 125; 75; 250 |]

let total points = Seq.scan (fun t p -> t + p) (List.head points) (List.tail points)

let modulo = fun i -> i % 10
let modulos points = Seq.map modulo (total points)
let quarterModulos = Seq.map (fun (afc, nfc) -> modulos afc, modulos nfc) quarterPoints

let payoff : int[,] = Array2D.zeroCreate 10 10

let payQuarter (afc, nfc, prize) = payoff.[nfc,afc] <- payoff.[nfc,afc] + prize
let payGame (afc, nfc) = Seq.iter payQuarter (Seq.zip3 afc nfc prizes)

Seq.iter payGame quarterModulos

payoff

This snippet is also runnable at tryfsharp.org. The results are interesting:

image

43% of the possible outcomes seem to have never occurred in the Super Bowl.

0 and 7 are indeed big winners, and 7 – 4 is by far the most valuable box. However, its reciprocal 4 – 7 is one of the least valuable of the winning boxes.