Re: Void initialization
On 19/12/2011 18:11, Steven Schveighoffer wrote: On Mon, 19 Dec 2011 12:24:18 -0500, Bear joanylepri...@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... snip You are. That the OP was talking about std.gc.malloc in D1, not the core.memory stuff in D2. Stewart.
Re: Void initialization
On 19/12/2011 12:12, bearophile wrote: Bear: snip 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]; snip 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
On Tue, 20 Dec 2011 09:22:46 -0500, Stewart Gordon smjg_1...@yahoo.com wrote: On 19/12/2011 18:11, Steven Schveighoffer wrote: On Mon, 19 Dec 2011 12:24:18 -0500, Bear joanylepri...@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... snip 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
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
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]; snip 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
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]; snip 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
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? snip 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
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
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. snip 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
Am 19.12.2011, 13:04 Uhr, schrieb Bear joanylepri...@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
Re: Void initialization
On Mon, 19 Dec 2011 07:04:20 -0500, Bear joanylepri...@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
Re: Void initialization
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
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
On Mon, 19 Dec 2011 12:24:18 -0500, Bear joanylepri...@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
Re: Void initialization
On Mon, 19 Dec 2011 18:52:44 +0100 Jacob Carlborg d...@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.
Re: Void initialization
On 2011-12-20 01:34, Jesse Phillips wrote: On Mon, 19 Dec 2011 18:52:44 +0100 Jacob Carlborgd...@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
Re: void initialization vs alignment holes
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
The situation is ugly, see the post in the main newsgroup: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=107153 Bye, bearophile
Re: void initialization vs alignment holes
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
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
Re: void initialization vs alignment holes
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. -- ... IXOYE
Re: void initialization vs alignment holes
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
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... -- ... IXOYE
Re: void initialization vs alignment holes
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
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). -- ... IXOYE