Time to move std.experimental.checkedint to std.checkedint ?
tsbockman
thomas.bockman at gmail.com
Wed Mar 31 09:01:39 UTC 2021
On Wednesday, 31 March 2021 at 04:49:01 UTC, Andrei Alexandrescu
wrote:
> On 3/31/21 12:47 AM, Andrei Alexandrescu wrote:
>> On 3/31/21 12:32 AM, tsbockman wrote:
>>> On Wednesday, 31 March 2021 at 03:32:40 UTC, Andrei
>>> Alexandrescu wrote:
>>>> On 3/30/21 7:01 PM, tsbockman wrote:
>>>>> Simply flipping compiler switches (the -ftrapv and -fwrapv
>>>>> flags in gcc Andrei mentioned earlier) won't work, because
>>>>> most high performance code contains some deliberate and
>>>>> correct examples of wrapping overflow, signed-unsigned
>>>>> reinterpretation, etc.
>>>>>
>>>>> Idiomatic Zig code (probably Ada, too) does contain this
>>>>> information. But, the selection of "real world" open source
>>>>> Zig code available for testing is limited right now, since
>>>>> Zig hasn't stabilized the language or the standard library
>>>>> yet.
>>>>
>>>> That's awfully close to "No true Scotsman".
>>>
>>> Just tossing out names of fallacies isn't really very helpful
>>> if you don't explain why you think it may apply here.
>>
>> I thought it's fairly clear
Thank you for explaining anyway.
>> - the claim is non-falsifiable: if code is faster without
>> checks, it is deemed so on account of tricks.
I've never disputed at any point that unchecked code is, by
nature, almost always faster than checked code - albeit often not
by much. I haven't attributed unchecked code's speed advantage to
"tricks" anywhere.
>> Code without checks could benefit of other, better
>> tricks, but their absence is explained by the small size of the
>> available corpus.
>
> s/Code without checks could benefit of other/Code with checks
> could benefit of other/
While I think it is true that "better tricks" can narrow the
performance gap between checked and unchecked code, that is not
at all what I was talking about at all in the paragraphs you
labeled "No true Scotsman".
Consider a C++ program similar to the following D program:
/////////////////////////////////////
module app;
import std.stdio : writeln, readln;
import std.conv : parse;
N randLCG(N)() @safe
if(is(N == int) || is(N == uint))
{
static N state = N(211210973);
// "Numerical Recipes" linear congruential generator:
return (state = N(1664525) * state + N(1013904223)); // can
and should wrap
}
double testDivisor(N, N divisor)(const(ulong) trials) @safe
if(is(N == int) || is(N == uint))
{
N count = 0;
foreach(n; 0 .. trials)
count += (randLCG!N() % divisor) == N(0); // can, but
should *not* wrap
return count / real(trials);
}
void main() {
string input = readln();
const trials = parse!ulong(input);
writeln(testDivisor!( int, 3)(trials));
writeln(testDivisor!(uint, 3)(trials));
}
/////////////////////////////////////
randLCG!( int, 3) requires -fwrapv and NOT -ftrapv to work as
intended.
randLCG!(uint, 3) works correctly no matter what.
testDivisor!( int, 3) requires -ftrapv and NOT -fwrapv to detect
unintended overflows.
testDivisor!(uint, 3) is always vulnerable to unintended
overflow, with or without -ftrapv.
So, neither -ftrapv nor -fwrapv causes an idiomatic C++ program
detect unintended overflows without false positives in the
general case. The compiler simply doesn't have enough information
available to do so, regardless of how much performance we are
willing to sacrifice. Instead, the source code of a C++ program
must first be modified by a real human being to make it
compatible with either -ftrapv or -fwrapv (which are mutually
exclusive).
The paper you linked earlier mentions this problem: "Finally
often integer overflows are known to be intentional or the
programmer has investigated it and determined it to be
acceptable. To address these use cases while still being useful
in reporting undesired integer overflows, a whitelist
functionality was introduced to enable users to specify certain
files or functions that should not be checked.
...
Second, our methodology for distinguishing intentional from
unintentional uses of wraparound is manual and subjective. The
manual effort required meant that we could only study a subset of
the errors..."
(See sections 5.3 and 6.1 of
https://dl.acm.org/doi/abs/10.1145/2743019)
Idiomatic Zig code already contains the information which the
researchers on that paper had to manually insert for all the
C/C++ code they tested. That is why my tests were limited to Zig,
because I don't have the time or motivation to go and determine
whether each and every potential overflow in GCC or Firefox or
whatever is intentional, just so that I can benchmark them with
-ftrapv enabled.
More information about the Digitalmars-d
mailing list