Author Topic: CPU instruction utilization with gcc  (Read 5058 times)

0 Members and 1 Guest are viewing this topic.

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4310
  • Country: nz
Re: CPU instruction utilization with gcc
« Reply #25 on: April 24, 2020, 10:01:56 pm »
OTOH, I don't see the point of using FP if you're strictly using FP as integers. It would require proper care from the developers side to begin with, and wouldn't make much sense unless you target CPUs with much faster FPU than their integer ALU. It's just asking for shooting yourself in the foot, and there's a very large probability this would lead to bugs due to improper use.

ALL programming, especially financial programming, requires proper care.

What is the difference between using 53 bit integers in an FP value and 32 bit integers in an integer value?  *Nothing*, except an extra 6 digits of precision. Using two 32 bit integers explicitly is just a PITA. Ok, modern C compilers have "long long". but that's new.

If you have a 64 bit CPU then of course you have a better working range. But there are still other advantages of FP. See below.

Quote
Just use integers. OK you were trying to make a point with FP, but frankly this doesn't make much sense in this context IMHO. Developers tempted to use FP for financial applications will usually do this to make their life easier, and we have a few examples of this leading to very bad software. If they have to use FP with even more caution than if they were using integers, that's pretty twisted.

It is precisely the same amount of caution -- you need to make sure you do operations that don't overflow the available range, and that don't produce inexact results, such as division.

The differences are:

1) an FP double holding an integer gives you 21 bits more precision -- more than 6 decimal digits.

2) if an integer operation overflows then you'll never know unless you very expensively check the result of every single operation. If an FP operation overflows the exact integer range or produces an inexact value in any other way then a flag is set that *stays* set until you clear it, so you can verify a whole series of calculations with a single check.

Using FP is not some slow dangerous kludge -- it is *safer*.
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6632
  • Country: fi
    • My home page and email address
Re: CPU instruction utilization with gcc
« Reply #26 on: April 24, 2020, 11:44:44 pm »
You don't use decimals. You use integers, just as BCD is fundamentally integer, and insert a "." character only when printing.
Then, your abstract decimal data type needs to have a separate field for the base power of ten -- which literally makes it a radix-10 floating point.
No.
Nice of you to not include the next sentence in that paragraph, "You can obviously have radix-10 fixed point types as well.", so you can say you used radix-10 fixed-point instead; i.e. integer values in units of 10-n of the base currency unit.

And I'm the one who gets called a troll here.  Hmph.

I absolutely did use FP values to represent money in all that software running on 68020+68882 and up to PowerPC. And, rarely, x86.
Explains a lot about the state of our financial system.  (Kidding!)

No, of course you can write safe and mathematically correct software using BCD, binary integers, floating-point numbers, or even ASCII decimal strings.

It is the obvious or naïve way of using floating-point numbers (not pure integers, but using decimals to represent fractional amounts of the base currency unit) in a financial system that is bad -- because often used values cannot be represented exactly in binary floating point.

Yes, you could even work out how to do all needed operations (including interest calculations) that work mathematically correctly even when you use floating-point numbers the obvious way, although it is nontrivial and slow, and you need to be Kahan sum -level careful when implementing each.

The fundamental problem lies, as usual, completely within us humans: what you mean exactly when you say "use floating-point types", and so on.
Even if you the original developer understand it, you also need to understand the rules by which your compiler works; and anyone modifying or maintaining the code later on must do so too.  I like to use the term "maintainability", because it is not just readability; it is about how easy or hard it is to understand the entire logic structure that governs the functioning of the program, and work within it.

For financial software, you don't get to do approximate totals; everything must match to the smallest currency unit recorded.  If you use floating point values like you would with normal numerical computation, with fractional parts representing fractional currency units, that won't happen unless your hardware FP is radix-10, because commonly used values cannot be represented exactly.  You can work around it, and brucehoult has outlined some experience on how that has been done by using integers only, in units of the smallest fraction needed, while still technically using FP and FP operations.  Another way to do it is via BCD.  A yet another way is via pure binary integers.  You can even use ASCII strings representing the numerical values -- it's easier than what one might think.

The issue is that just writing the code and claim it does what is asked, is just a small part of software engineering.  Sometimes you use an inefficient implementation, because the tradeoff between efficiency and maintainability warrants it.  If you need something to be efficient and reliable, you test the hell out of it, and acknowledge that if it needs to be "modified", it is better rewritten from scratch using the full sets of (changed) requirements, and ensure the requirements defining the operational rules are well documented.

It would be so nice to write code just for myself, and to hell with maintainability -- but then we wouldn't be able to stand on the shoulders of giants; we'd just all be standing out there in the field, reinventing the same wheels again and again.

To circle back at the original topic, this also means that the subset of instructions say GCC uses isn't really indicative of much: it is difficult to tell if the unused subset is unused because GCC is inefficient, or because that subset is just not useful.  Similarly for BCD: just because a bunch of programmers cannot immediately see a killer use case for it, does not mean there isn't one.
« Last Edit: April 24, 2020, 11:47:12 pm by Nominal Animal »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf