www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Void initialization

reply Bear <joanyleprince yahoo.fr> writes:
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?
Dec 19 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Dec 19 2011
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
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.
Dec 20 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Dec 20 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
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.
Dec 20 2011
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 20/12/2011 18:12, bearophile wrote:
<snip>
 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.
Dec 20 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Dec 20 2011
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 20/12/2011 22:19, bearophile wrote:
<snip>
 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.
Dec 20 2011
prev sibling next sibling parent Trass3r <un known.com> writes:
Am 19.12.2011, 13:04 Uhr, schrieb Bear <joanyleprince yahoo.fr>:

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

std.array.uninitializedArray
Dec 19 2011
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 19 Dec 2011 07:04:20 -0500, Bear <joanyleprince yahoo.fr> 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
Dec 19 2011
parent reply Bear <joanyleprince yahoo.fr> writes:
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.
Dec 19 2011
next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
Dec 19 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-12-20 01:34, Jesse Phillips wrote:
 On Mon, 19 Dec 2011 18:52:44 +0100
 Jacob Carlborg<doob me.com>  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
Dec 19 2011
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 19/12/2011 18:11, Steven Schveighoffer wrote:
 On Mon, 19 Dec 2011 12:24:18 -0500, Bear <joanyleprince yahoo.fr> 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.
Dec 20 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 19 Dec 2011 12:24:18 -0500, Bear <joanyleprince yahoo.fr> 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
Dec 19 2011
prev sibling next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
On Mon, 19 Dec 2011 18:52:44 +0100
Jacob Carlborg <doob me.com> 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.
Dec 19 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 20 Dec 2011 09:22:46 -0500, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 On 19/12/2011 18:11, Steven Schveighoffer wrote:
 On Mon, 19 Dec 2011 12:24:18 -0500, Bear <joanyleprince yahoo.fr> 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
Dec 20 2011
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
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];
Dec 20 2011