Dconf 2015 talks...

Era Scarecrow via Digitalmars-d digitalmars-d at puremagic.com
Sun Feb 7 16:54:24 PST 2016


On Sunday, 7 February 2016 at 22:27:40 UTC, Joseph Rushton 
Wakeling wrote:
> On Monday, 25 January 2016 at 22:06:31 UTC, Era Scarecrow wrote:
> What you describe makes sense, but I don't quite follow what 
> you mean in one particular case:
>
>>  Technically alloca simply returns the current sp, then adds 
>> to it the number of bytes you requested. This means you have 
>> to run it at the function stack where you want to use it (and 
>> not in a called function, otherwise corruption). So inlined 
>> functions where alloca's data would remain would be a must.

  That's the low level assembly language that's generated i'm 
referring to; At least based on what i've read and seen for code 
output from a compiler to a .s file or similar.

> I don't quite follow your remark about inlined functions; do 
> you mean that the function where the RNG instance is generated 
> must be inlined?  (That would make sense in order to avoid the 
> internal state being deallocated immediately.)

Assuming alloca moves to the inlined function. Although i had 
another idea thrown in my head where the memory would be 
pre-allocated and you could just point to it when requested via 
an allocator. So assume

@alloca(sizeof(int)) struct RNG {

  During instantiation it would know the size ahead of time and 
just append that to the end of the structure. That extra padding 
space could be handled manually instead.

  this(int seed) {
    state = cast(void*)(this+1);
  }

  But this forced type breaking is quite clunky (and obviously the 
wrong way to write it).

  I recall in C there was suppose to be a way to attach an array 
(of unknown size) immediately following a struct by making the 
length of the array 0, then accessing it directly. But you'd 
still need to guarantee somehow that the access rights are in 
place and not referencing other data which you could screw up 
(via optimizations or something).

> I think there might be more complications here than just 
> allocating individual RNG instances, though (which can happen 
> quite early on in the program); what about stuff like random 
> algorithms (RandomCover, RandomSample) which might be generated 
> deep in internal loops, passed to other functionality as 
> rvalues, etc. etc.?

  Either they use more stack space, or they act normally after 
their call is done and are deallocated normally (automatically, 
unless they are passed outside of the scope where they were 
generated).

> It might be simpler, in practice, to just have the state 
> refcounted.
>
>>>>  I suppose the alternate is an option to skip/throw-away 
>>>> some numbers that should've been consumed
>>> I'm not sure I follow what you mean here or why you think 
>>> this would work?  Could you give a concrete example?

>>   void skip(int x) {assert(x>0); while(x--) popfront();}

>> rnd.take(10).writeln;  //loosely based on talk examples
>> rnd.skip(10);          //skips the 'consumed' numbers.
>> rnd.take(10).writeln;  //won't have identical output


> I'm afraid that's not really viable :-(
> But the problem is, in the general case, you can't anticipate 
> how many random variates may be popped from your random number 
> generator inside a function.

  True; Perhaps have one RNG for seeding and one RNG for passing, 
then reseed after passing the function off, although how far deep 
some of this could go with it's deeper copying; I don't know.

  Perhaps RNG should be a class outright, which probably removes a 
lot of these problems.


More information about the Digitalmars-d mailing list