digitalmars.D - Cleaned up C++
- Walter Bright (2/2) Apr 22 2015 I'd missed this post on reddit:
- weaselcat (3/5) Apr 22 2015 what's up with people constantly equating garbage collection to
- ketmar (3/9) Apr 22 2015 they are ignorant, that's it.=
- bearophile (6/12) Apr 22 2015 In D you don't put everything on the heap. D is less
- Walter Bright (2/4) Apr 22 2015 ??
- bearophile (7/10) Apr 23 2015 In Ada standard library you have safe fixed-size stack-allocated
- Walter Bright (10/18) Apr 23 2015 I used to use alloca() here and there, but eventually removed it all. Th...
- John Colvin (9/32) Apr 23 2015 I used to think this was totally wrong, but over time I've come
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (4/7) Apr 23 2015 If you have a random distribution of sizes then allocating the
- weaselcat (2/25) Apr 23 2015 Is there a reason scopebuffer isn't part of the documentation?
- Walter Bright (2/3) Apr 23 2015 Everyone hated it :-) but me.
- Daniel Murphy (3/4) Apr 24 2015 And by that Walter means the interface was highly unsafe and he didn't w...
- deadalnix (9/32) Apr 23 2015 For arbitrary large, you can always do something like :
- Walter Bright (9/16) Apr 23 2015 You can, but it just doesn't pay off. Even if you found a case that did,...
- John Colvin (2/24) Apr 24 2015 Except of course that alloca is a lot cheaper than malloc/free.
- Walter Bright (3/4) Apr 24 2015 That's not necessarily true. But in any case, go ahead and use it if you...
- ponce (6/11) Apr 24 2015 Do you have a guess for why and when it could not be faster than
- John Colvin (26/39) Apr 24 2015 one reason why it might be faster is that e.g. gcc can produce
- Walter Bright (3/25) Apr 24 2015 It's a cowboy implementation that's fine until it someone tries a largis...
- Iain Buclaw via Digitalmars-d (5/35) Apr 24 2015 this:
- Walter Bright (4/5) Apr 25 2015 A large enough value can not just case stack overflow, but can cause the...
- deadalnix (2/7) Apr 24 2015 It is, unless one go the bump the pointer/never free road.
- Walter Bright (2/9) Apr 24 2015 I wouldn't assume that. A large array on the stack will have memory cach...
- ponce (17/19) Apr 22 2015 Thanks for the mention. I must have forgotten some. I should put
- Walter Bright (4/15) Apr 22 2015 Most of the implicit initializations become "dead stores" and are remove...
- John Colvin (7/33) Apr 22 2015 Is it even possible to contrive a case where
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (2/9) Apr 22 2015 Allocation of large arrays.
- John Colvin (5/15) Apr 22 2015 That doesn't really answer the question without some more
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (20/38) Apr 23 2015 I think it does.
- John Colvin (8/17) Apr 23 2015 Yes, there are times the compiler can't optimise the dead stores
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (13/16) Apr 23 2015 Well, it can be a lot more than 1-5% in special situations if you
- Iain Buclaw via Digitalmars-d (12/34) Apr 23 2015 There are two states each local variable can be assigned.
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (5/16) Apr 23 2015 Proving how indexing of an array hits the array in a nontrivial
- Walter Bright (2/6) Apr 22 2015 And you can still initialize with '= void'.
- Adam D. Ruppe (3/4) Apr 22 2015 This was my tip of the week two TWID's ago!
- Walter Bright (2/6) Apr 22 2015 Yup!
- deadalnix (4/11) Apr 22 2015 I'd say it is very unlikely. If the compiler wan't see it, then
- John Colvin (7/19) Apr 23 2015 This was my thinking. I guess you could have something like this:
- Iain Buclaw via Digitalmars-d (83/121) Apr 23 2015 Right, on simple types (scalars, pointers) which have a trivial
- Andrei Alexandrescu (2/7) Apr 25 2015 I've seen statically-sized arrays causing problems. -- Andrei
- John Colvin (3/14) Apr 25 2015 Care to outline an example?
- Andrei Alexandrescu (13/25) Apr 25 2015 Many examples have to do with sentinel-terminated buffers. Start with e....
- ponce (2/3) Apr 26 2015 http://p0nce.github.io/d-idioms/#How-does-D-improve-on-C++17?
- Laeeth Isharc (3/8) Apr 26 2015 excellent.
- Baz (3/12) Apr 26 2015 Luke 4:24 "nobody is prophet in his own country"
- ponce (2/16) Apr 26 2015 Lesson taken: should have put a less aggressive title.
- Laeeth Isharc (11/29) Apr 27 2015 Not necessarily. The people who complain loudly constitute a
I'd missed this post on reddit: http://www.reddit.com/r/programming/comments/30wj8g/managing_cs_complexity_or_learning_to_enjoy_c/cpx41ix
Apr 22 2015
On Wednesday, 22 April 2015 at 19:29:08 UTC, Walter Bright wrote:D is just another of those “Let's put everything on the heap”-languages that do then of course need GC.what's up with people constantly equating garbage collection to being the same as java?
Apr 22 2015
On Wed, 22 Apr 2015 19:32:46 +0000, weaselcat wrote:On Wednesday, 22 April 2015 at 19:29:08 UTC, Walter Bright wrote:=80=9D-languagesD is just another of those =E2=80=9CLet's put everything on the heap=E2=they are ignorant, that's it.=that do then of course need GC.=20 what's up with people constantly equating garbage collection to being the same as java?
Apr 22 2015
weaselcat:On Wednesday, 22 April 2015 at 19:29:08 UTC, Walter Bright wrote:In D you don't put everything on the heap. D is less stack-friendly than Ada (and probably Rust too), but in D you allocate lot of small stuff on the stack. Bye, bearophileD is just another of those “Let's put everything on the heap”-languages that do then of course need GC.what's up with people constantly equating garbage collection to being the same as java?
Apr 22 2015
On 4/22/2015 2:58 PM, bearophile wrote:D is less stack-friendly than Ada (and probably Rust too),??
Apr 22 2015
Walter Bright:On 4/22/2015 2:58 PM, bearophile wrote:In Ada standard library you have safe fixed-size stack-allocated associative arrays. In D you can't even allocate safely a dynamically-sized 1D array on the stack, and forget about doing it for 2D. Enough said. Bye, bearophileD is less stack-friendly than Ada (and probably Rust too),??
Apr 23 2015
On 4/23/2015 1:10 AM, bearophile wrote:Walter Bright:I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes: a) 0 b) 1 c) arbitrarily large Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization". I don't agree with your assessment at all.On 4/22/2015 2:58 PM, bearophile wrote:In Ada standard library you have safe fixed-size stack-allocated associative arrays. In D you can't even allocate safely a dynamically-sized 1D array on the stack, and forget about doing it for 2D. Enough said.D is less stack-friendly than Ada (and probably Rust too),??
Apr 23 2015
On Thursday, 23 April 2015 at 18:37:47 UTC, Walter Bright wrote:On 4/23/2015 1:10 AM, bearophile wrote:I used to think this was totally wrong, but over time I've come to see your point. The ideal for me would be a dynamically sized stack array (C99 style, not alloca) with a compile-time maximum size. Then you wrap that in a library type that decides/defines what to do when the size is exceeded (e.g. move to GC heap a la scopeBuffer), but in practice it's not a big win over just stack allocating the maximum size all the time (again, like scopeBuffer).Walter Bright:I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes: a) 0 b) 1 c) arbitrarily large Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization". I don't agree with your assessment at all.On 4/22/2015 2:58 PM, bearophile wrote:In Ada standard library you have safe fixed-size stack-allocated associative arrays. In D you can't even allocate safely a dynamically-sized 1D array on the stack, and forget about doing it for 2D. Enough said.D is less stack-friendly than Ada (and probably Rust too),??
Apr 23 2015
On Thursday, 23 April 2015 at 20:40:36 UTC, John Colvin wrote:scopeBuffer), but in practice it's not a big win over just stack allocating the maximum size all the time (again, like scopeBuffer).If you have a random distribution of sizes then allocating the maximum will use twice as much memory. That affects cache performance.
Apr 23 2015
On Thursday, 23 April 2015 at 18:37:47 UTC, Walter Bright wrote:On 4/23/2015 1:10 AM, bearophile wrote:Is there a reason scopebuffer isn't part of the documentation?Walter Bright:I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes: a) 0 b) 1 c) arbitrarily large Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization". I don't agree with your assessment at all.On 4/22/2015 2:58 PM, bearophile wrote:In Ada standard library you have safe fixed-size stack-allocated associative arrays. In D you can't even allocate safely a dynamically-sized 1D array on the stack, and forget about doing it for 2D. Enough said.D is less stack-friendly than Ada (and probably Rust too),??
Apr 23 2015
On 4/23/2015 2:54 PM, weaselcat wrote:Is there a reason scopebuffer isn't part of the documentation?Everyone hated it :-) but me.
Apr 23 2015
"Walter Bright" wrote in message news:mhc7am$942$1 digitalmars.com...Everyone hated it :-) but me.And by that Walter means the interface was highly unsafe and he didn't want to change it.
Apr 24 2015
On Thursday, 23 April 2015 at 18:37:47 UTC, Walter Bright wrote:On 4/23/2015 1:10 AM, bearophile wrote:For arbitrary large, you can always do something like : Item* itemPtr = (arbitrarylarge < thresold) ? alloca(arbitrarylarge) : GC.alloc(arbitrarylarge); One extra check compared to a heap allocation is not going to make things terrible, and it is likely to be very predictible anyway (most arbitrarylarge size are actually small in practice). The compiler could even do it at optimizer level.Walter Bright:I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes: a) 0 b) 1 c) arbitrarily large Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization". I don't agree with your assessment at all.On 4/22/2015 2:58 PM, bearophile wrote:In Ada standard library you have safe fixed-size stack-allocated associative arrays. In D you can't even allocate safely a dynamically-sized 1D array on the stack, and forget about doing it for 2D. Enough said.D is less stack-friendly than Ada (and probably Rust too),??
Apr 23 2015
On 4/23/2015 3:11 PM, deadalnix wrote:For arbitrary large, you can always do something like : Item* itemPtr = (arbitrarylarge < thresold) ? alloca(arbitrarylarge) : GC.alloc(arbitrarylarge); One extra check compared to a heap allocation is not going to make things terrible, and it is likely to be very predictible anyway (most arbitrarylarge size are actually small in practice).You can, but it just doesn't pay off. Even if you found a case that did, it doesn't mean it pays off in general, and so would be poor advice. BTW, since alloca() doesn't survive function scope, might as well use malloc/free instead of the GC. Or do like I've done and have an array of preallocated larger buffers. I.e. if you've gotten to tuning code at this level, the compiler picking things automatically for you is unlikely to be helpful. Hence my not being convinced by bearophile's assessment.
Apr 23 2015
On Friday, 24 April 2015 at 01:54:11 UTC, Walter Bright wrote:On 4/23/2015 3:11 PM, deadalnix wrote:Except of course that alloca is a lot cheaper than malloc/free.For arbitrary large, you can always do something like : Item* itemPtr = (arbitrarylarge < thresold) ? alloca(arbitrarylarge) : GC.alloc(arbitrarylarge); One extra check compared to a heap allocation is not going to make things terrible, and it is likely to be very predictible anyway (most arbitrarylarge size are actually small in practice).You can, but it just doesn't pay off. Even if you found a case that did, it doesn't mean it pays off in general, and so would be poor advice. BTW, since alloca() doesn't survive function scope, might as well use malloc/free instead of the GC. Or do like I've done and have an array of preallocated larger buffers. I.e. if you've gotten to tuning code at this level, the compiler picking things automatically for you is unlikely to be helpful. Hence my not being convinced by bearophile's assessment.
Apr 24 2015
On 4/24/2015 12:23 AM, John Colvin wrote:Except of course that alloca is a lot cheaper than malloc/free.That's not necessarily true. But in any case, go ahead and use it if you like. Just prepare to benchmark and be disappointed :-)
Apr 24 2015
On Friday, 24 April 2015 at 08:16:40 UTC, Walter Bright wrote:On 4/24/2015 12:23 AM, John Colvin wrote:Do you have a guess for why and when it could not be faster than malloc in times? I have some difficulty imagining a reason (yet I have sometimes found malloc faster than aligned_malloc which is another odd thing).Except of course that alloca is a lot cheaper than malloc/free.That's not necessarily true. But in any case, go ahead and use it if you like. Just prepare to benchmark and be disappointed :-)
Apr 24 2015
On Friday, 24 April 2015 at 12:34:19 UTC, ponce wrote:On Friday, 24 April 2015 at 08:16:40 UTC, Walter Bright wrote:one reason why it might be faster is that e.g. gcc can produce code like this: #include<alloca.h> void bar(char* a); void foo(unsigned int n) { char *a = (char*)alloca(n); bar(a); } foo: movl %edi, %eax pushq %rbp addq $46, %rax movq %rsp, %rbp shrq $4, %rax salq $4, %rax subq %rax, %rsp leaq 31(%rsp), %rdi andq $-32, %rdi call bar leave ret which is neat. Now of course a push-the-pointer malloc/free implementation could perhaps be (in theory) optimised to be as small as this, but is that ever actually the case?On 4/24/2015 12:23 AM, John Colvin wrote:Do you have a guess for why and when it could not be faster than malloc in times? I have some difficulty imagining a reason (yet I have sometimes found malloc faster than aligned_malloc which is another odd thing).Except of course that alloca is a lot cheaper than malloc/free.That's not necessarily true. But in any case, go ahead and use it if you like. Just prepare to benchmark and be disappointed :-)
Apr 24 2015
On 4/24/2015 5:59 AM, John Colvin wrote:one reason why it might be faster is that e.g. gcc can produce code like this: #include<alloca.h> void bar(char* a); void foo(unsigned int n) { char *a = (char*)alloca(n); bar(a); } foo: movl %edi, %eax pushq %rbp addq $46, %rax movq %rsp, %rbp shrq $4, %rax salq $4, %rax subq %rax, %rsp leaq 31(%rsp), %rdi andq $-32, %rdi call bar leave ret which is neat.It's a cowboy implementation that's fine until it someone tries a largish value of n.
Apr 24 2015
On 25 Apr 2015 01:25, "Walter Bright via Digitalmars-d" < digitalmars-d puremagic.com> wrote:On 4/24/2015 5:59 AM, John Colvin wrote:this:one reason why it might be faster is that e.g. gcc can produce code likevalue of n.#include<alloca.h> void bar(char* a); void foo(unsigned int n) { char *a = (char*)alloca(n); bar(a); } foo: movl %edi, %eax pushq %rbp addq $46, %rax movq %rsp, %rbp shrq $4, %rax salq $4, %rax subq %rax, %rsp leaq 31(%rsp), %rdi andq $-32, %rdi call bar leave ret which is neat.It's a cowboy implementation that's fine until it someone tries a largishI wonder just how large... IIRC I think the limit on ubyte arrays is 1M?
Apr 24 2015
On 4/24/2015 11:51 PM, Iain Buclaw via Digitalmars-d wrote:I wonder just how large... IIRC I think the limit on ubyte arrays is 1M?A large enough value can not just case stack overflow, but can cause the stack pointer to be anywhere in the address space. I don't know of a limit on ubyte arrays.
Apr 25 2015
On Friday, 24 April 2015 at 08:16:40 UTC, Walter Bright wrote:On 4/24/2015 12:23 AM, John Colvin wrote:It is, unless one go the bump the pointer/never free road.Except of course that alloca is a lot cheaper than malloc/free.That's not necessarily true. But in any case, go ahead and use it if you like. Just prepare to benchmark and be disappointed :-)
Apr 24 2015
On 4/24/2015 10:27 AM, deadalnix wrote:On Friday, 24 April 2015 at 08:16:40 UTC, Walter Bright wrote:I wouldn't assume that. A large array on the stack will have memory caching issues.On 4/24/2015 12:23 AM, John Colvin wrote:It is, unless one go the bump the pointer/never free road.Except of course that alloca is a lot cheaper than malloc/free.That's not necessarily true. But in any case, go ahead and use it if you like. Just prepare to benchmark and be disappointed :-)
Apr 24 2015
On Wednesday, 22 April 2015 at 19:29:08 UTC, Walter Bright wrote:I'd missed this post on reddit: http://www.reddit.com/r/programming/comments/30wj8g/managing_cs_complexity_or_learning_to_enjoy_c/cpx41ixThanks for the mention. I must have forgotten some. I should put in in a d-idioms anyway. I didn't appreciate how important default initialization was before having to fix a non-deterministic, release-only, time-dependent bug in a video encoder some months ago. Just because of 2 uninitialized variables (C++ doesn't require member initialization in constructor). If one of them was _exactly equal to 1_ by virtue of randomness, then it would perform from 0 to 2 billions of motion estimation steps, which is very slow but not a total halt. A watchdog mechanism would detect this and reboot, hence labelling the bug "a deadlock". It would disappear in debug mode since variables would be initialized then. That gives a totally other meaning to "zero cost abstractions" since in three weeks of investigation I could have speed-up the program by ~5%, much more than the supposed slowdown of variable initialization.
Apr 22 2015
On 4/22/2015 12:51 PM, ponce wrote:I didn't appreciate how important default initialization was before having to fix a non-deterministic, release-only, time-dependent bug in a video encoder some months ago. Just because of 2 uninitialized variables (C++ doesn't require member initialization in constructor). If one of them was _exactly equal to 1_ by virtue of randomness, then it would perform from 0 to 2 billions of motion estimation steps, which is very slow but not a total halt. A watchdog mechanism would detect this and reboot, hence labelling the bug "a deadlock". It would disappear in debug mode since variables would be initialized then.The default initialization comes from bitter personal experience, much like yours!That gives a totally other meaning to "zero cost abstractions" since in three weeks of investigation I could have speed-up the program by ~5%, much more than the supposed slowdown of variable initialization.Most of the implicit initializations become "dead stores" and are removed anyway by the optimizer.
Apr 22 2015
On Wednesday, 22 April 2015 at 20:29:49 UTC, Walter Bright wrote:On 4/22/2015 12:51 PM, ponce wrote:Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".I didn't appreciate how important default initialization was before having to fix a non-deterministic, release-only, time-dependent bug in a video encoder some months ago. Just because of 2 uninitialized variables (C++ doesn't require member initialization in constructor). If one of them was _exactly equal to 1_ by virtue of randomness, then it would perform from 0 to 2 billions of motion estimation steps, which is very slow but not a total halt. A watchdog mechanism would detect this and reboot, hence labelling the bug "a deadlock". It would disappear in debug mode since variables would be initialized then.The default initialization comes from bitter personal experience, much like yours!That gives a totally other meaning to "zero cost abstractions" since in three weeks of investigation I could have speed-up the program by ~5%, much more than the supposed slowdown of variable initialization.Most of the implicit initializations become "dead stores" and are removed anyway by the optimizer.
Apr 22 2015
On Wednesday, 22 April 2015 at 20:36:12 UTC, John Colvin wrote:Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".Allocation of large arrays.
Apr 22 2015
On Wednesday, 22 April 2015 at 21:59:48 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 22 April 2015 at 20:36:12 UTC, John Colvin wrote:That doesn't really answer the question without some more context. Can you give a specific example where all 3 points are satisfied?Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".Allocation of large arrays.
Apr 22 2015
On Wednesday, 22 April 2015 at 22:26:45 UTC, John Colvin wrote:On Wednesday, 22 April 2015 at 21:59:48 UTC, Ola Fosheim Grøstad wrote:I think it does. Compilers cannot tell what goes on because they cannot figure out nontrivial loop invariants without guidance. You need something like a theorem prover (coq?)... Compilers may not be about to tell arrays won't be touched because of memory barriers when calling external functions, so they have to complete initialization before that. Presumably a Rust compiler could do better...On Wednesday, 22 April 2015 at 20:36:12 UTC, John Colvin wrote:That doesn't really answer the question without some more context.Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".Allocation of large arrays.Can you give a specific example where all 3 points are satisfied?Not sure why you would need it, plenty of cases where compilers will fail. E.g. queues between threads (like real time threads) where you allocate in one thread and fill out data in another thread. Any preallocation done on large data structures or frequently reinitialized data structures may perform better without explicit initialization. For a system level language I think it would be better to verify that you don't use noninitialized memory using a theorem prover (sanitizer) or to use guards (like NaN). Automatic initialization is also a source of bugs.
Apr 23 2015
On Thursday, 23 April 2015 at 14:29:01 UTC, Ola Fosheim Grøstad wrote:Yes, there are times the compiler can't optimise the dead stores away. Obviously these dead stores are not free. What I don't see is a good example of when that cost matters. There are cases where you might really need to grab an extra 1-5%, at which point you are hand optimising and = void is a reasonable tool.Can you give a specific example where all 3 points are satisfied?Not sure why you would need it, plenty of cases where compilers will fail. E.g. queues between threads (like real time threads) where you allocate in one thread and fill out data in another thread. Any preallocation done on large data structures or frequently reinitialized data structures may perform better without explicit initialization.
Apr 23 2015
On Thursday, 23 April 2015 at 14:50:26 UTC, John Colvin wrote:There are cases where you might really need to grab an extra 1-5%, at which point you are hand optimising and = void is a reasonable tool.Well, it can be a lot more than 1-5% in special situations if you hand over a small header request with a bundled array to fill in, so "=void" can be important. But the real down side by making automatic initialization part of the language semantics is that you cannot do machine verfication where you detect cases where you forgot actual initialization. E.g. indexing where you should start at 1 and not 0. That's not so good for correctness. It's the same issue with modular arithmetics which actually remove overflows from integer operations, but then you cannot use machine verification to detect overflow either (unless you are happy with a large number of false positives).
Apr 23 2015
On 23 April 2015 at 16:28, via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Wednesday, 22 April 2015 at 22:26:45 UTC, John Colvin wrote:There are two states each local variable can be assigned. 1. Used 2. Read int a = 1; // a = Used return a; // a = Read printf("%d\n", a); // a = Read int b = a; // b = Used, a = Read int c = void; // c = Unused If a variable is unused, it's a dead variable. If a variable is used but not read, it's a dead variable. Simple. :-)On Wednesday, 22 April 2015 at 21:59:48 UTC, Ola Fosheim Grøstad wrote:I think it does. Compilers cannot tell what goes on because they cannot figure out nontrivial loop invariants without guidance. You need something like a theorem prover (coq?)...On Wednesday, 22 April 2015 at 20:36:12 UTC, John Colvin wrote:That doesn't really answer the question without some more context.Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".Allocation of large arrays.
Apr 23 2015
On Thursday, 23 April 2015 at 14:55:42 UTC, Iain Buclaw wrote:There are two states each local variable can be assigned. 1. Used 2. Read int a = 1; // a = Used return a; // a = Read printf("%d\n", a); // a = Read int b = a; // b = Used, a = Read int c = void; // c = Unused If a variable is unused, it's a dead variable. If a variable is used but not read, it's a dead variable. Simple. :-)Proving how indexing of an array hits the array in a nontrivial loop is intractable for large N (any parameter you like). (you also don't deal with binary true/false, but three outcomes: satisfiable, unsatisfiable and unknown)
Apr 23 2015
On 4/22/2015 1:36 PM, John Colvin wrote:Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact?And you can still initialize with '= void'.
Apr 22 2015
On Wednesday, 22 April 2015 at 22:41:33 UTC, Walter Bright wrote:And you can still initialize with '= void'.This was my tip of the week two TWID's ago! http://arsdnet.net/this-week-in-d/apr-12.html
Apr 22 2015
On 4/22/2015 3:52 PM, Adam D. Ruppe wrote:On Wednesday, 22 April 2015 at 22:41:33 UTC, Walter Bright wrote:Yup!And you can still initialize with '= void'.This was my tip of the week two TWID's ago! http://arsdnet.net/this-week-in-d/apr-12.html
Apr 22 2015
On Wednesday, 22 April 2015 at 20:36:12 UTC, John Colvin wrote:Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".I'd say it is very unlikely. If the compiler wan't see it, then it means the code is non trivial, and if it is non trivial, it is not an extra store that is going to make any difference.
Apr 22 2015
On Thursday, 23 April 2015 at 01:45:14 UTC, deadalnix wrote:On Wednesday, 22 April 2015 at 20:36:12 UTC, John Colvin wrote:This was my thinking. I guess you could have something like this: extern(C) void myCheapInitialiser(float*, size_t); float[256] a; myCheapInitialiser(a.ptr, a.length); sort(a); writeln(a.stride(2).sum());Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".I'd say it is very unlikely. If the compiler wan't see it, then it means the code is non trivial, and if it is non trivial, it is not an extra store that is going to make any difference.
Apr 23 2015
On Wednesday, 22 April 2015 at 20:29:49 UTC, Walter Bright wrote:Right, on simple types (scalars, pointers) which have a trivial initialisation, the compiler is able to track their value until it is read and use DCE to remove previous initialisations up to that point. (Contrived) Examples: void dce1() { int dead_int; printf("Dead Int\n"); } void dce2() { int inited_later; int dead_int; inited_later = 42; printf("Initialized Int = %d\n", inited_later); } --- gdc -O -fdump-tree-optimized=stderr dce.d dce1 () { __builtin_puts (&"Dead Int"[0]); return; } dce2 () { __builtin_printf ("Initialized Int = %d\n", 42); return; } --- As pointed out, there are limitations when it comes to types which have a complex initialiser. On 22 April 2015 at 22:36, John Colvin via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 4/22/2015 12:51 PM, ponce wrote:I didn't appreciate how important default initialization was before having to fix a non-deterministic, release-only, time-dependent bug in a video encoder some months ago. Just because of 2 uninitialized variables (C++ doesn't require member initialization in constructor). If one of them was _exactly equal to 1_ by virtue of randomness, then it would perform from 0 to 2 billions of motion estimation steps, which is very slow but not a total halt. A watchdog mechanism would detect this and reboot, hence labelling the bug "a deadlock". It would disappear in debug mode since variables would be initialized then.The default initialization comes from bitter personal experience, much like yours!That gives a totally other meaning to "zero cost abstractions" since in three weeks of investigation I could have speed-up the program by ~5%, much more than the supposed slowdown of variable initialization.Most of the implicit initializations become "dead stores" and are removed anyway by the optimizer.Is it even possible to contrive a case where 1) The default initialisation stores are technically dead andint arrayInit() { return 0xdeadbeef; } void main() { int[ushort.max] dead_array = arrayInit(); printf("Dead Array\n"); }2) Modern compilers can't tell they are dead and elide them andActually - gdc can DCE the array initialisation at -O3, but I'd like to do better than that in future... gdc -O3 -fdump-tree-optimized=stderr dce.d D main () { unsigned int ivtmp.20; int dead_array[65535]; unsigned int _1; void * _13; <bb 2>: ivtmp.20_12 = (unsigned int) &dead_array; _1 = (unsigned int) &MEM[(void *)&dead_array + 262128B]; <bb 3>: _13 = (void *) ivtmp.20_16; MEM[base: _13, offset: 0B] = { -559038737, -559038737, -559038737, -559038737 }; ivtmp.20_3 = ivtmp.20_16 + 16; if (_1 == ivtmp.20_3) goto <bb 4>; else goto <bb 3>; <bb 4>: __builtin_puts (&"Dead Array"[0]); dead_array ={v} {CLOBBER}; return 0; }3) Doing the initialisation has a significant performance impact?Short answer, no. time ./a.out Dead Array real 0m0.001s user 0m0.000s sys 0m0.001s Worded answer, static array overflow analysis means that you can't get an array much higher than 1M, and the compiler can quite happily vectorised the initialisation process for you so there's fewer loops to go round. However if there was a 'lazy + impure' initialiser, that would be a different story. :-) Iain.
Apr 23 2015
On 4/22/15 1:36 PM, John Colvin wrote:Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".I've seen statically-sized arrays causing problems. -- Andrei
Apr 25 2015
On Saturday, 25 April 2015 at 21:26:25 UTC, Andrei Alexandrescu wrote:On 4/22/15 1:36 PM, John Colvin wrote:Care to outline an example?Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".I've seen statically-sized arrays causing problems. -- Andrei
Apr 25 2015
On 4/25/15 3:23 PM, John Colvin wrote:On Saturday, 25 April 2015 at 21:26:25 UTC, Andrei Alexandrescu wrote:Many examples have to do with sentinel-terminated buffers. Start with e.g. char buf[1024] = void; buf[0] = 0; ... The rest of the function makes sure it keeps the invariant that the buffer is zero-terminated. This is difficult for compilers to divine (never saw any to do so). So you have either code that's officially unsafe because it uses uninitialized data, or slow code because it zeroes the entire kilobyte. No more need to get into details here, because... IT'S HACKATHON TIME! I'll post my ideas next. AndreiOn 4/22/15 1:36 PM, John Colvin wrote:Care to outline an example?Is it even possible to contrive a case where 1) The default initialisation stores are technically dead and 2) Modern compilers can't tell they are dead and elide them and 3) Doing the initialisation has a significant performance impact? The boring example is "extra code causes instruction cache misses".I've seen statically-sized arrays causing problems. -- Andrei
Apr 25 2015
On Wednesday, 22 April 2015 at 19:51:23 UTC, ponce wrote:I should put in in a d-idioms anyway.http://p0nce.github.io/d-idioms/#How-does-D-improve-on-C++17?
Apr 26 2015
On Sunday, 26 April 2015 at 09:26:11 UTC, ponce wrote:On Wednesday, 22 April 2015 at 19:51:23 UTC, ponce wrote:excellent. I linked it here: http://wiki.dlang.org/Coming_FromI should put in in a d-idioms anyway.http://p0nce.github.io/d-idioms/#How-does-D-improve-on-C++17?
Apr 26 2015
On Sunday, 26 April 2015 at 12:04:20 UTC, Laeeth Isharc wrote:On Sunday, 26 April 2015 at 09:26:11 UTC, ponce wrote:Luke 4:24 "nobody is prophet in his own country" http://www.reddit.com/r/programming/comments/33x6lj/how_does_d_improve_on_c17/On Wednesday, 22 April 2015 at 19:51:23 UTC, ponce wrote:excellent. I linked it here: http://wiki.dlang.org/Coming_FromI should put in in a d-idioms anyway.http://p0nce.github.io/d-idioms/#How-does-D-improve-on-C++17?
Apr 26 2015
On Sunday, 26 April 2015 at 14:28:11 UTC, Baz wrote:On Sunday, 26 April 2015 at 12:04:20 UTC, Laeeth Isharc wrote:Lesson taken: should have put a less aggressive title.On Sunday, 26 April 2015 at 09:26:11 UTC, ponce wrote:Luke 4:24 "nobody is prophet in his own country" http://www.reddit.com/r/programming/comments/33x6lj/how_does_d_improve_on_c17/On Wednesday, 22 April 2015 at 19:51:23 UTC, ponce wrote:excellent. I linked it here: http://wiki.dlang.org/Coming_FromI should put in in a d-idioms anyway.http://p0nce.github.io/d-idioms/#How-does-D-improve-on-C++17?
Apr 26 2015
On Sunday, 26 April 2015 at 19:13:33 UTC, ponce wrote:On Sunday, 26 April 2015 at 14:28:11 UTC, Baz wrote:Not necessarily. The people who complain loudly constitute a tiny subset of those who are ultimately influenced. One can't walk through life in fear of criticism, and if you believe D is superior in this respect and backed it up (which it seemed to me you did), then I think it's more effective to say so and prepare for the inevitable brickbats than to placate those who will always find a reason to attack you ;) In any case, some really good stuff in your idioms. Maybe worth turning into a longer blog piece that recounts in a personal voice your experience of using D as a C++ guy.On Sunday, 26 April 2015 at 12:04:20 UTC, Laeeth Isharc wrote:Lesson taken: should have put a less aggressive title.On Sunday, 26 April 2015 at 09:26:11 UTC, ponce wrote:Luke 4:24 "nobody is prophet in his own country" http://www.reddit.com/r/programming/comments/33x6lj/how_does_d_improve_on_c17/On Wednesday, 22 April 2015 at 19:51:23 UTC, ponce wrote:excellent. I linked it here: http://wiki.dlang.org/Coming_FromI should put in in a d-idioms anyway.http://p0nce.github.io/d-idioms/#How-does-D-improve-on-C++17?
Apr 27 2015
On Monday, 27 April 2015 at 07:45:30 UTC, Laeeth Isharc wrote:On Sunday, 26 April 2015 at 19:13:33 UTC, ponce wrote:Good advice, thanks! It seems the more assertive tones often get less criticism.Lesson taken: should have put a less aggressive title.Not necessarily. The people who complain loudly constitute a tiny subset of those who are ultimately influenced. One can't walk through life in fear of criticism, and if you believe D is superior in this respect and backed it up (which it seemed to me you did), then I think it's more effective to say so and prepare for the inevitable brickbats than to placate those who will always find a reason to attack you ;)In any case, some really good stuff in your idioms. Maybe worth turning into a longer blog piece that recounts in a personal voice your experience of using D as a C++ guy.Thanks. There might be errors in places. Bringing D in the workplace often bring incredible resistance and arguments. I've heard it all over the years: - "D can't be scripted" (yes it can) - "D isn't fast enough" - "D isn't much used and is 10 years old, there must be problems" - "D isn't used enough" Much like C++ was met with resistance? Meanwhile D programs get written and consistently over-deliver on promises.
Apr 27 2015
On Mon, 27 Apr 2015 08:23:26 +0000, ponce wrote:Bringing D in the workplace often bring incredible resistance and arguments. =20 I've heard it all over the years: - "D can't be scripted" (yes it can) - "D isn't fast enough" - "D isn't much used and is 10 years old, there must be problems" - "D isn't used enough" =20 Much like C++ was met with resistance? Meanwhile D programs get written and consistently over-deliver on promises.D has one thing that kills C++ instantly, though: modules (and=20 declaration order). anyone who had a joy to work on big project with C or=20 C++ will sell his soul for module system.=
Apr 27 2015