Re: Default initialization of static array faster than void initialization

2019-11-08 Thread kinke via Digitalmars-d-learn

On Friday, 8 November 2019 at 16:49:37 UTC, wolframw wrote:
I compiled with dmd -O -inline -release -noboundscheck 
-mcpu=avx2 and ran the tests with the m array being 
default-initialized in one run and void-initialized in another 
run.

The results:
Default-initialized: 245 ms, 495 μs, and 2 hnsecs
Void-initialized: 324 ms, 697 μs, and 2 hnsecs


If you care about performance, you're much better off with LDC or 
GDC. DMD v2.089 takes 11.7 ms on my Win64 machine, LDC (`ldc2 -O 
-run gist.d`) v1.18 0.27 ms - that's 43x faster.




Re: Default initialization of static array faster than void initialization

2019-11-08 Thread Ali Çehreli via Digitalmars-d-learn
One correction: I think you mean "using" a default-initialized array is 
faster (not the initialization itself).


Another observation: dmd -O makes both cases slower! Hm?

Ali



Default initialization of static array faster than void initialization

2019-11-08 Thread wolframw via Digitalmars-d-learn

Hi,

Chapter 12.15.2 of the spec explains that void initialization of 
a static array can be faster than default initialization. This 
seems logical because the array entries don't need to be set to 
NaN. However, when I ran some tests for my matrix implementation, 
it seemed that the default-initialized array is quite a bit 
faster.


The code (and the disassembly) is at 
https://gist.github.com/wolframw/73f94f73a822c7593e0a7af411fa97ac


I compiled with dmd -O -inline -release -noboundscheck -mcpu=avx2 
and ran the tests with the m array being default-initialized in 
one run and void-initialized in another run.

The results:
Default-initialized: 245 ms, 495 μs, and 2 hnsecs
Void-initialized: 324 ms, 697 μs, and 2 hnsecs

What the heck?
I've also inspected the disassembly and found an interesting 
difference in the benchmark loop (annotated with "start of loop" 
and "end of loop" in both disassemblies). It seems to me like the 
compiler partially unrolled the loop in both cases, but in the 
default-allocation case it discards every second result of the 
multiplication and saves each other result to the sink matrix. In 
the void-initialized version, it seems like each result is stored 
in the sink matrix.
I don't see how such a difference can be caused by the different 
initialization strategies. Is there something I'm not considering?
Also, if the compiler is smart enough to figure out that it can 
discard some of the results, why doesn't it just do away with the 
entire loop and run the multiplication only once? Since both 
input matrices are immutable and opBinary is pure, it is 
guaranteed that the result is always the same, isn't it?


Re: Struct Postblit Void Initialization

2017-07-30 Thread Moritz Maxeiner via Digitalmars-d-learn

On Sunday, 30 July 2017 at 19:22:07 UTC, Jiyan wrote:

Hey,
just wanted to know whether something like this would be 
possible sowmehow:


struct S
{
int m;
int n;
this(this)
{
m = void;
n = n;
}
}

So not the whole struct is moved everytime f.e. a function is 
called, but only n has to be "filled"


I'll assume you mean copying (as per the title) not moving 
(because moving doesn't make sense to me in this context); use a 
dedicated method:


struct S
{
int m, n;
S sparseDup()
{
S obj;
obj.n = n;
return obj;
}
}


Re: Struct Postblit Void Initialization

2017-07-30 Thread Jiyan via Digitalmars-d-learn

On Sunday, 30 July 2017 at 19:32:48 UTC, Eugene Wissner wrote:

On Sunday, 30 July 2017 at 19:22:07 UTC, Jiyan wrote:

Hey,
just wanted to know whether something like this would be 
possible sowmehow:


struct S
{
int m;
int n;
this(this)
{
m = void;
n = n;
}
}

So not the whole struct is moved everytime f.e. a function is 
called, but only n has to be "filled"


this(this) is called after the struct is copied. Doing 
something in the postblit constructor is too late. The second 
thing is that the struct is copied with memcpy. What you 
propose would require 2 memcpy calls to copy the first part of 
the struct and then the second part. Besides it is difficult to 
implement, it may reduce the performance of the copying since 
memcpy is optimized to copy memory chunks.


Ok thank you :)


Re: Struct Postblit Void Initialization

2017-07-30 Thread Eugene Wissner via Digitalmars-d-learn

On Sunday, 30 July 2017 at 19:22:07 UTC, Jiyan wrote:

Hey,
just wanted to know whether something like this would be 
possible sowmehow:


struct S
{
int m;
int n;
this(this)
{
m = void;
n = n;
}
}

So not the whole struct is moved everytime f.e. a function is 
called, but only n has to be "filled"


this(this) is called after the struct is copied. Doing something 
in the postblit constructor is too late. The second thing is that 
the struct is copied with memcpy. What you propose would require 
2 memcpy calls to copy the first part of the struct and then the 
second part. Besides it is difficult to implement, it may reduce 
the performance of the copying since memcpy is optimized to copy 
memory chunks.


Struct Postblit Void Initialization

2017-07-30 Thread Jiyan via Digitalmars-d-learn

Hey,
just wanted to know whether something like this would be possible 
sowmehow:


struct S
{
int m;
int n;
this(this)
{
m = void;
n = n;
}
}

So not the whole struct is moved everytime f.e. a function is 
called, but only n has to be "filled"




Re: Void initialization

2011-12-20 Thread Stewart Gordon

On 20/12/2011 22:19, bearophile wrote:


That's also why I have said a better solution is to wrap that code into a 
function
template, so there is no need for an alias.



So what you actually meant was to make TF a template parameter?  That would 
make more sense.

I can understand an alias being an intermediate step towards refactoring complex code into 
a template, but if you present it as part of a solution in simple cases like this then 
it's bound to get people wondering why on earth you're doing it, and possibly detract from 
what you're doing to actually (attempt to) solve the problem with the original code.


Stewart.


Re: Void initialization

2011-12-20 Thread bearophile
Stewart Gordon:

> I don't quite understand - why not just use float as it is? OK, so 
> abbreviating it to TF 
> saves 9 characters on that line, but the alias declaration and its trailing 
> line break 
> take up 16 characters, so you're not saving space at all.

It's not a way to save chars, it's a way to avoid bugs, making the code my DRY.


> Moreover, the style guide discourages meaningless type aliases.

That's also why I have said a better solution is to wrap that code into a 
function template, so there is no need for an alias.
6


> import std.stdio, std.gc;
> 
> void main() {
>  size_t x = 42;
> 
>  float[] f = cast(float[]) std.gc.malloc(x*4);
>  writefln(f.length);
> 
>  alias float TF;
>  f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x];
>  writefln(f.length);
> }

I didn't know this. It's handy.

Bye,
bearophile


Re: Void initialization

2011-12-20 Thread Stewart Gordon

On 20/12/2011 18:12, bearophile wrote:


Because in that code I have used three times a type (TF), auto allows to remove 
only
one of them. The alias is not the best solution (a better solution is to put 
that code
into a templated function), but repeating the same generic type more than one 
time is
usually a source of bugs.


I don't quite understand - why not just use float as it is?  OK, so abbreviating it to TF 
saves 9 characters on that line, but the alias declaration and its trailing line break 
take up 16 characters, so you're not saving space at all.


Moreover, the style guide discourages meaningless type aliases.  (OK, so there are things 
I disagree with there, like using spaces not tabs for indentation, but that's another matter.)



- std.gc.malloc returns the array with correct length according to my quick 
test, so the
use of [0..x] is redundant


Really? Well, as I have said I have not tested that code.
Generally GC functions return a void*, so to create an array I think you need 
to slice
it...


If that were the case, the OP's code wouldn't have compiled.  I made out that the OP was 
getting these errors at runtime, not compiletime.



What is the code of your quick test?



import std.stdio, std.gc;

void main() {
size_t x = 42;

float[] f = cast(float[]) std.gc.malloc(x*4);
writefln(f.length);

alias float TF;
f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x];
writefln(f.length);
}


Stewart.


Re: Void initialization

2011-12-20 Thread Timon Gehr

On 12/20/2011 07:12 PM, bearophile wrote:

Stewart Gordon:


On 19/12/2011 12:12, bearophile wrote:



Try something like this (untested):

alias float TF;
TF[] f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x];



I fail to see any real difference from the OP's code:

- Why the alias?


Because in that code I have used three times a type (TF), auto allows to remove 
only one of them. The alias is not the best solution (a better solution is to 
put that code into a templated function), but repeating the same generic type 
more than one time is usually a source of bugs.



- std.gc.malloc returns the array with correct length according to my quick 
test, so the
use of [0..x] is redundant


Really? Well, as I have said I have not tested that code.
Generally GC functions return a void*, so to create an array I think you need 
to slice it... What is the code of your quick test?



- using TF.sizeof instead of 4 might fix things if on the user's platform float 
isn't 4
bytes long.


In D I think float is always 4 bytes long.



  Otherwise, while using .sizeof instead of a hard-coded number is better
practice, it isn't going to get rid of an AV.


I don't know what an AV is.

Bye,
bearophile


Access Violation.


Re: Void initialization

2011-12-20 Thread bearophile
Stewart Gordon:

> On 19/12/2011 12:12, bearophile wrote:

> > Try something like this (untested):
> >
> > alias float TF;
> > TF[] f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x];
> 
> 
> I fail to see any real difference from the OP's code:
> 
> - Why the alias?

Because in that code I have used three times a type (TF), auto allows to remove 
only one of them. The alias is not the best solution (a better solution is to 
put that code into a templated function), but repeating the same generic type 
more than one time is usually a source of bugs.


> - std.gc.malloc returns the array with correct length according to my quick 
> test, so the 
> use of [0..x] is redundant

Really? Well, as I have said I have not tested that code.
Generally GC functions return a void*, so to create an array I think you need 
to slice it... What is the code of your quick test?


> - using TF.sizeof instead of 4 might fix things if on the user's platform 
> float isn't 4 
> bytes long.

In D I think float is always 4 bytes long.


>  Otherwise, while using .sizeof instead of a hard-coded number is better 
> practice, it isn't going to get rid of an AV.

I don't know what an AV is.

Bye,
bearophile


Re: Void initialization

2011-12-20 Thread Timon Gehr

On 12/19/2011 01:04 PM, Bear wrote:

Using D1, I have a program that creates tons of float[] ; for performance
reasons, I would like them to be uninitialized.
I've tried replacing

float[] f = new float[x];
by
float[] f = cast(float[])std.gc.malloc(x*4);


Unfortunately I keep running into "Access violation" and sometimes "Array
bounds error". I've tried adding

setTypeInfo(typeid(float), f.ptr);
and hasNoPointer(f.ptr);

which didn't work.

However
f[] = float.nan;
solved the problem, but kinda defeats the purpose of using malloc...
What am I doing wrong?


Are you using GDC?
https://bitbucket.org/goshawk/gdc/issue/287/casting-between-array-types-is-broken

If so, this is the workaround:

float[] f = (cast(float[])std.gc.malloc(x*4))[0..x];


Re: Void initialization

2011-12-20 Thread Steven Schveighoffer
On Tue, 20 Dec 2011 09:22:46 -0500, Stewart Gordon   
wrote:



On 19/12/2011 18:11, Steven Schveighoffer wrote:

On Mon, 19 Dec 2011 12:24:18 -0500, Bear  wrote:


gc.malloc actually returns void[]


http://www.d-programming-language.org/phobos/core_memory.html#malloc

Looks like void* to me...

Or is there another function I'm not aware of? I think it should be  
GC.malloc, not

gc.malloc, so maybe I'm missing something...



You are.  That the OP was talking about std.gc.malloc in D1, not the  
core.memory stuff in D2.


Ah, my bad.  Having never used phobos1, I have no idea how it is  
implemented, so I can't help here.


Well, I did use it for a week before thinking "there has to be something  
better" and found Tango :)


I think bearophile has fell for the same thing.

-Steve


Re: Void initialization

2011-12-20 Thread Stewart Gordon

On 19/12/2011 12:12, bearophile wrote:

Bear:



float[] f = cast(float[])std.gc.malloc(x*4);


Try something like this (untested):

alias float TF;
TF[] f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x];



I fail to see any real difference from the OP's code:

- Why the alias?
- std.gc.malloc returns the array with correct length according to my quick test, so the 
use of [0..x] is redundant
- using TF.sizeof instead of 4 might fix things if on the user's platform float isn't 4 
bytes long.  Otherwise, while using .sizeof instead of a hard-coded number is better 
practice, it isn't going to get rid of an AV.


But knowing what platform the OP is using and having a complete testcase for the AVs/ABEs 
might help to understand what is going on.


Stewart.


Re: Void initialization

2011-12-20 Thread Stewart Gordon

On 19/12/2011 18:11, Steven Schveighoffer wrote:

On Mon, 19 Dec 2011 12:24:18 -0500, Bear  wrote:


gc.malloc actually returns void[]


http://www.d-programming-language.org/phobos/core_memory.html#malloc

Looks like void* to me...

Or is there another function I'm not aware of? I think it should be GC.malloc, 
not
gc.malloc, so maybe I'm missing something...



You are.  That the OP was talking about std.gc.malloc in D1, not the 
core.memory stuff in D2.

Stewart.



Re: Void initialization

2011-12-19 Thread Jacob Carlborg

On 2011-12-20 01:34, Jesse Phillips wrote:

On Mon, 19 Dec 2011 18:52:44 +0100
Jacob Carlborg  wrote:


You can always make the variable uninitialized using "void", don't
know if that what is what you're looking for.

float[] f = void;



He is trying to create an array where the elements are not initialized.


Ah, I see.

--
/Jacob Carlborg


Re: Void initialization

2011-12-19 Thread Jesse Phillips
On Mon, 19 Dec 2011 18:52:44 +0100
Jacob Carlborg  wrote:

> You can always make the variable uninitialized using "void", don't
> know if that what is what you're looking for.
> 
> float[] f = void;
> 

He is trying to create an array where the elements are not initialized.


Re: Void initialization

2011-12-19 Thread Steven Schveighoffer

On Mon, 19 Dec 2011 12:24:18 -0500, Bear  wrote:


gc.malloc actually returns void[]


http://www.d-programming-language.org/phobos/core_memory.html#malloc

Looks like void* to me...

Or is there another function I'm not aware of?  I think it should be  
GC.malloc, not gc.malloc, so maybe I'm missing something...


Bearophile's suggestion seems to work though, but it doesn't seem to  
improve
performance for some reason... I guess I'll have to find some other way  
to make my

prog quicker.


Actually, an issue with bearophile's suggestion is that it allocates a  
block marked as containing pointers.  Such a block is bulk-initialized to  
0.


Try this:

float[] f = (cast(float*)GC.malloc(x * TF.sizeof, GC.BlkAttr.NO_SCAN))[0  
.. x];


This will leave the memory uninitialized.

And depending on the usage, this optimization may or may not make a huge  
difference.


-Steve


Re: Void initialization

2011-12-19 Thread Jacob Carlborg

On 2011-12-19 18:24, Bear wrote:

gc.malloc actually returns void[]
Bearophile's suggestion seems to work though, but it doesn't seem to improve
performance for some reason... I guess I'll have to find some other way to make 
my
prog quicker.


You can always make the variable uninitialized using "void", don't know 
if that what is what you're looking for.


float[] f = void;

--
/Jacob Carlborg


Re: Void initialization

2011-12-19 Thread Bear
gc.malloc actually returns void[]
Bearophile's suggestion seems to work though, but it doesn't seem to improve
performance for some reason... I guess I'll have to find some other way to make 
my
prog quicker.


Re: Void initialization

2011-12-19 Thread Steven Schveighoffer

On Mon, 19 Dec 2011 07:04:20 -0500, Bear  wrote:


Using D1, I have a program that creates tons of float[] ; for performance
reasons, I would like them to be uninitialized.
I've tried replacing

float[] f = new float[x];
by
float[] f = cast(float[])std.gc.malloc(x*4);


this is wrong.  a float[] slice is actually a struct, whereas gc.malloc  
returns a pointer.


What you have done is cast a pointer into a pointer+length struct, leaving  
anyones guess as to what the length is set to.  I don't even know why this  
compiles...


A slice is a pointer + length, and you can slice a pointer to "add a  
length" to it.  Follow bearophile's suggestion.



However
f[] = float.nan;
solved the problem, but kinda defeats the purpose of using malloc...
What am I doing wrong?


If this works, it's not doing what you think :)

-Steve


Re: Void initialization

2011-12-19 Thread Trass3r

Am 19.12.2011, 13:04 Uhr, schrieb Bear :


Using D1, I have a program that creates tons of float[] ; for performance
reasons, I would like them to be uninitialized.


std.array.uninitializedArray


Re: Void initialization

2011-12-19 Thread bearophile
Bear:

> Using D1, I have a program that creates tons of float[] ; for performance
> reasons, I would like them to be uninitialized.
> I've tried replacing
> 
> float[] f = new float[x];
> by
> float[] f = cast(float[])std.gc.malloc(x*4);

Try something like this (untested):

alias float TF;
TF[] f = (cast(TF*)std.gc.malloc(x * TF.sizeof))[0 .. x];

Using x*4 is error-prone. I suggest to wrap that code inside a templated 
function, where T is the type of the items, to avoid some bugs.

Bye,
bearophile


Void initialization

2011-12-19 Thread Bear
Using D1, I have a program that creates tons of float[] ; for performance
reasons, I would like them to be uninitialized.
I've tried replacing

float[] f = new float[x];
by
float[] f = cast(float[])std.gc.malloc(x*4);


Unfortunately I keep running into "Access violation" and sometimes "Array
bounds error". I've tried adding

setTypeInfo(typeid(float), f.ptr);
and hasNoPointer(f.ptr);

which didn't work.

However
f[] = float.nan;
solved the problem, but kinda defeats the purpose of using malloc...
What am I doing wrong?


Re: Dynamic array void initialization

2011-03-08 Thread Tom

El 08/03/2011 21:42, Kai Meyer escribió:

On 03/08/2011 02:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


Any reason you don't just do this:

S[] ss;
ss.reserve(5)
foreach(i; 0..i)
ss ~= S(1, 2);

I think that would not do default initialization on any of the elements,
and it would ensure that the dynamic array is own "grown" once.


Nope, you're right. That'll work for me.

Thank you,
Tom;



Re: Dynamic array void initialization

2011-03-08 Thread Kai Meyer

On 03/08/2011 05:42 PM, Kai Meyer wrote:

On 03/08/2011 02:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


Any reason you don't just do this:

S[] ss;
ss.reserve(5)
foreach(i; 0..i)
ss ~= S(1, 2);

I think that would not do default initialization on any of the elements,
and it would ensure that the dynamic array is own "grown" once.


Sorry,
foreach(i; 0..5)

That's what I get for writing code with out trying to run it


Re: Dynamic array void initialization

2011-03-08 Thread Kai Meyer

On 03/08/2011 02:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


Any reason you don't just do this:

S[] ss;
ss.reserve(5)
foreach(i; 0..i)
  ss ~= S(1, 2);

I think that would not do default initialization on any of the elements, 
and it would ensure that the dynamic array is own "grown" once.


Re: Dynamic array void initialization

2011-03-08 Thread spir

On 03/08/2011 11:57 PM, Steven Schveighoffer wrote:

On Tue, 08 Mar 2011 17:48:37 -0500, Tom  wrote:


http://d.puremagic.com/issues/show_bug.cgi?id=5603

This is really sad. This kind of stuff is a must for performance. D is
disappointing me too much yet :(



There is always c's malloc, or you can try using the GC malloc directly. For
application specific needs, it might be sufficient. However, a builtin
language/library feature must be very robust and handle all cases.


I recently discovered the GC module refactored (with all funcs now integrated 
into the type): very good job; everything is now clear and easy to use.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: Dynamic array void initialization

2011-03-08 Thread Steven Schveighoffer

On Tue, 08 Mar 2011 17:48:37 -0500, Tom  wrote:


http://d.puremagic.com/issues/show_bug.cgi?id=5603

This is really sad. This kind of stuff is a must for performance. D is  
disappointing me too much yet :(




There is always c's malloc, or you can try using the GC malloc directly.   
For application specific needs, it might be sufficient.  However, a  
builtin language/library feature must be very robust and handle all cases.


-Steve


Re: Dynamic array void initialization

2011-03-08 Thread Tom

El 08/03/2011 19:03, Steven Schveighoffer escribió:

On Tue, 08 Mar 2011 16:53:08 -0500, Ali Çehreli  wrote:


On 03/08/2011 01:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


There is std.array.reserve:

import std.array;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss;
reserve(ss, 5);

// or if you want to confuse yourself (and me):
ss.reserve(5); // same thing as above

foreach (ref s; ss)
s = S(1, 2);

return 0;
}


Some clarifications:

it's not std.array.reserve, it's object.reserve, always present, no need
to import.

I believe if the type contains pointers the GC still writes 0s to the
unused data to prevent false pointers. However, reserve on an int or a
struct that just contains ints should not pre-initialize.

reserve ensures appropriate space for appending, it does *not* alter the
array's length. So your foreach loop would not execute (at that point,
ss.length is still 0).

To work properly, you would need to use the append operator.

Bearophile has requested an ability to create a dynamic array
uninitialized, and I think there is a bug report for that. Currently,
there is no "easy way" to do it.

-Steve


http://d.puremagic.com/issues/show_bug.cgi?id=5603

This is really sad. This kind of stuff is a must for performance. D is 
disappointing me too much yet :(




Re: Dynamic array void initialization

2011-03-08 Thread Ali Çehreli

On 03/08/2011 02:03 PM, Steven Schveighoffer wrote:

> it's not std.array.reserve, it's object.reserve, always present, no need
> to import.

Thanks. The reserve that I found in array.d is 
std.array.Appender(T).reserve.


Ali



Re: Dynamic array void initialization

2011-03-08 Thread Steven Schveighoffer

On Tue, 08 Mar 2011 16:53:08 -0500, Ali Çehreli  wrote:


On 03/08/2011 01:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


There is std.array.reserve:

import std.array;

struct S {
 int i;
 int j;
}

int main(string[] args) {
 S[] ss;
 reserve(ss, 5);

 // or if you want to confuse yourself (and me):
 ss.reserve(5);  // same thing as above

 foreach (ref s; ss)
 s = S(1, 2);

 return 0;
}


Some clarifications:

it's not std.array.reserve, it's object.reserve, always present, no need  
to import.


I believe if the type contains pointers the GC still writes 0s to the  
unused data to prevent false pointers. However, reserve on an int or a  
struct that just contains ints should not pre-initialize.


reserve ensures appropriate space for appending, it does *not* alter the  
array's length.  So your foreach loop would not execute (at that point,  
ss.length is still 0).


To work properly, you would need to use the append operator.

Bearophile has requested an ability to create a dynamic array  
uninitialized, and I think there is a bug report for that.  Currently,  
there is no "easy way" to do it.


-Steve


Re: Dynamic array void initialization

2011-03-08 Thread Ali Çehreli

On 03/08/2011 01:34 PM, Tom wrote:

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just
give and access violation error).

I need to create a dynamic array of some struct, but don't want defer
contained elements initialization (for performance reasons).

Tom;


There is std.array.reserve:

import std.array;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss;
reserve(ss, 5);

// or if you want to confuse yourself (and me):
ss.reserve(5);  // same thing as above

foreach (ref s; ss)
s = S(1, 2);

return 0;
}

Ali



Dynamic array void initialization

2011-03-08 Thread Tom

import std.stdio;

struct S {
int i;
int j;
}

int main(string[] args) {
S[] ss = void;
ss.length = 5;
foreach (ref s; ss)
s = S(1, 2);
return 0;
}

Is the above code correct? (it doesn't work... it blows away or just 
give and access violation error).


I need to create a dynamic array of some struct, but don't want defer 
contained elements initialization (for performance reasons).


Tom;


Re: void initialization vs alignment holes

2010-03-07 Thread bearophile
strtr:
> static if( S.sizeof == members.sizeof )
>  S s = void;
> else
>  S s;

You can use something like this :-)

import std.stdio: writeln;

int unusedBytesStruct(S)() if (is(S == struct)) {
int totUsed;
foreach (field; S.init.tupleof)
totUsed += field.sizeof;
return cast(int)S.sizeof - totUsed;
}

struct S1 {
byte s;
double d;
}

align(1) struct S2 {
byte s;
double d;
}

struct T {
double d;
int x;
short s;
ubyte u1, u2;
}

void main() {
writeln(unusedBytesStruct!S1); // 7
writeln(unusedBytesStruct!S2); // 0
writeln(unusedBytesStruct!T);  // 0
}

Bye,
bearophile


Re: void initialization vs alignment holes

2010-03-07 Thread bearophile
The situation is ugly, see the post in the main newsgroup:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=107153

Bye,
bearophile


Re: void initialization vs alignment holes

2010-03-07 Thread bearophile
strtr:
>Might this be worth an explicit mention on digitalmars?<

Currently the documentation has some semantic holes that must be filled :-)


> Suppose I'd still would like to use void optimizations, how do you clear the 
> holes manually?

If you need to fill the holes manually, then probably it's better to let the 
compiler clear the whole struct automatically at the beginning.
If you really want to clear the struct instance manually, I can see few ways to 
do it:
- don't leave holes in the struct, use an align(1)
- use a memset(&somestruct, o, sizeof(typeof(somestruct)));  This is preferred 
because it's safe, short, and fast.
- Add strategically placed dummy items inside the struct, in the same position 
and size of the holes it has, and then assign them to zero normally. Holes do 
change in size for different operating systems (think about the type real, that 
has a different length across different operating systems, 10, 12 and 16 
bytes), so this seems a bit too much complex way to solve the problem.


> Not that I'm touching void any more, just interested :)

Sometimes void structs are useful, in performance critical spots of the 
program. But I suggest you to avoid it when possible. You have to be careful, 
because they can contain spurious pointers, that the conservative GC will use 
to keep objects alive. This happens especially if the struct contains pointers 
in the first place.


>I suspect this isn't the case for void initialization; if my struct has some 
>alignment hole I better not void initialize it if ever I want to compare it 
>with somthing.<
>And unless you will never compare the struct, as the garbage bits will also be 
>compared.<

I don't know. A well implemented opEquals and opCmp among structs has to ignore 
the contents of the holes.
I have to do experiments *and* to go look at Phobos source code. In any case 
the D documentation must explain 100% about how such things work, the compiler 
writer must not be free to choose here.

Bye,
bearophile


Re: void initialization vs alignment holes

2010-03-06 Thread strtr
BCS Wrote:
> IIRC zero filling a block is likely cheaper that zero filling holes in it. 
> I'd avoid "=void" unless you know you will be copying structs into the space 
> (that will copy the holes as well). 
And unless you will never compare the struct, as the garbage bits will also be 
compared.
I was thinking about using void in the struct opCall, bad idea.
Maybe add 

static if( S.sizeof == members.sizeof )
 S s = void;
else
 S s;

:D


Re: void initialization vs alignment holes

2010-03-06 Thread BCS

Hello Strtr,



Suppose I'd still would like to use void optimizations, how do you
clear the holes manually?


IIRC zero filling a block is likely cheaper that zero filling holes in it. 
I'd avoid "=void" unless you know you will be copying structs into the space 
(that will copy the holes as well). 


--
... <





Re: void initialization vs alignment holes

2010-03-06 Thread strtr
bearophile Wrote:

> strtr:
> 
> > I suspect this isn't the case for void initialization; if my struct has 
> > some alignment hole I better not void initialize it if ever I want to 
> > compare it with something.
> > Is this correct?
> 
> That has to be correct.
Might this be worth an explicit mention on digitalmars?

> 
> 
> > Would you ever have an alignment hole if all the struct contains are basic 
> > types(excluding bool)?
> 
> On Windows the sizeof of this struct is 16 bytes, so there is a big hole in 
> the middle:
> 
> struct Foo {
>   short s;
>   double d;
> }
> 
> This is 12 bytes long, it has a smaller hole, even if the data needs the same 
> space, because doubles need a stronger alignment:
> 
> struct Foo {
>   short s;
>   int[2] i;
> }
> 

I should have thought of that, thanks ;)

Suppose I'd still would like to use void optimizations, how do you clear the 
holes manually?
align(1) and add a dummy member initialized to 0 to fill?
Or would this not be an optimization any more because the way dmd aligned it 
optimally for the registers (or something) ?

Not that I'm touching void any more, just interested :)




Re: void initialization vs alignment holes

2010-03-06 Thread BCS

Hello Strtr,


BCS Wrote:


Hello Strtr,


Would you ever have an alignment hole if all the struct contains are
basic types(excluding bool)?


real, char[n], byte[n] and short[m] (for n%4 != 0 and m%2 != 0) might
be an issue.


Sounds logical, thanks!



I don't actually *know* those will be a problem, but...


--
... <





Re: void initialization vs alignment holes

2010-03-06 Thread strtr
BCS Wrote:

> Hello Strtr,
> 
> > Would you ever have an alignment hole if all the struct contains are
> > basic types(excluding bool)?
> 
> real, char[n], byte[n] and short[m] (for n%4 != 0 and m%2 != 0) might be 
> an issue.
> 
Sounds logical, thanks!




Re: void initialization vs alignment holes

2010-03-06 Thread BCS

Hello Strtr,


Would you ever have an alignment hole if all the struct contains are
basic types(excluding bool)?


real, char[n], byte[n] and short[m] (for n%4 != 0 and m%2 != 0) might be 
an issue.





--
... <





Re: void initialization vs alignment holes

2010-03-06 Thread bearophile
strtr:

> I suspect this isn't the case for void initialization; if my struct has some 
> alignment hole I better not void initialize it if ever I want to compare it 
> with somthing.
> Is this correct?

That has to be correct.


> Would you ever have an alignment hole if all the struct contains are basic 
> types(excluding bool)?

On Windows the sizeof of this struct is 16 bytes, so there is a big hole in the 
middle:

struct Foo {
  short s;
  double d;
}

This is 12 bytes long, it has a smaller hole, even if the data needs the same 
space, because doubles need a stronger alignment:

struct Foo {
  short s;
  int[2] i;
}

Bye,
bearophile


void initialization vs alignment holes

2010-03-06 Thread strtr
This is probably going a bit above my head, but

"the existence of alignment holes in the objects is accounted for, usually by 
setting them all to 0 upon initialization"

I suspect this isn't the case for void initialization; if my struct has some 
alignment hole I better not void initialize it if ever I want to compare it 
with somthing.
Is this correct?
Would you ever have an alignment hole if all the struct contains are basic 
types(excluding bool)?