www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Fast matrix struct

reply "Ryan" <ryan.n.leach gmail.com> writes:
I'm writing a Matrix struct that I plan to use for some number 
crunching, which will be intensive at times. So I want it to be 
fast.

Will I do better by manually managing the memory myself with 
malloc and free in the constructors/destructor or just using 
plain D arrays?

The manual way I could bypass the GC and bounds checks. I don't 
need (or want) any of the fancy appending concatenation and the 
potential slowdowns from the heap allocations that comes with the 
builtin arrays.

But I have to wonder, if I just don't use those features, will it 
be just as fast with the GC (assuming I compile out the bounds 
checks with the -release compiler option)?

Right now my strategy is to malloc one large chunk of memory in 
the constructor (and postblit) and treat the 2-d matrix as a 1-d 
array internally. Then just use pointer arithmetic to access the 
elements.

I know the best way to know is just to test. But writing both 
versions would take a LOT of work, and I'm looking for guidance 
about which path will probably be most fruitful.

Thanks,
Dec 14 2014
next sibling parent "anonymous" <anonymous nowhere.ut> writes:
On Sunday, 14 December 2014 at 22:14:55 UTC, Ryan wrote:
 I'm writing a Matrix struct that I plan to use for some number 
 crunching, which will be intensive at times. So I want it to be 
 fast.

 Will I do better by manually managing the memory myself with 
 malloc and free in the constructors/destructor or just using 
 plain D arrays?

 The manual way I could bypass the GC and bounds checks. I don't 
 need (or want) any of the fancy appending concatenation and the 
 potential slowdowns from the heap allocations that comes with 
 the builtin arrays.

 But I have to wonder, if I just don't use those features, will 
 it be just as fast with the GC (assuming I compile out the 
 bounds checks with the -release compiler option)?

 Right now my strategy is to malloc one large chunk of memory in 
 the constructor (and postblit) and treat the 2-d matrix as a 
 1-d array internally. Then just use pointer arithmetic to 
 access the elements.

 I know the best way to know is just to test. But writing both 
 versions would take a LOT of work, and I'm looking for guidance 
 about which path will probably be most fruitful.

 Thanks,
Just a hint about "a LOT of work": ---------- struct Hop { version(noGC) // defined with a custom compiler switch -version=noGC private T[] arr; else std.container.Array!T arr; } ---------- The GC-free array already exist in the standard library.
Dec 14 2014
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Sunday, 14 December 2014 at 22:14:55 UTC, Ryan wrote:
 I'm writing a Matrix struct that I plan to use for some number 
 crunching, which will be intensive at times. So I want it to be 
 fast.

 Will I do better by manually managing the memory myself with 
 malloc and free in the constructors/destructor or just using 
 plain D arrays?

 The manual way I could bypass the GC and bounds checks. I don't 
 need (or want) any of the fancy appending concatenation and the 
 potential slowdowns from the heap allocations that comes with 
 the builtin arrays.

 But I have to wonder, if I just don't use those features, will 
 it be just as fast with the GC (assuming I compile out the 
 bounds checks with the -release compiler option)?

 Right now my strategy is to malloc one large chunk of memory in 
 the constructor (and postblit) and treat the 2-d matrix as a 
 1-d array internally. Then just use pointer arithmetic to 
 access the elements.

 I know the best way to know is just to test. But writing both 
 versions would take a LOT of work, and I'm looking for guidance 
 about which path will probably be most fruitful.

 Thanks,
There should be no performance hit for using builtin array indexing if you compile with -noboundscheck or the equivalent for ldc/gdc. The reverse situation is great though ("Huh, that looks garbled" <recompile with bounds checks enabled, run and hit a RangeError> "Oh look, that's where it went wrong"). Even if for some reason you do hit a problem (e.g. you only want to disable bounds checks for one very hot loop) then adding a quick .ptr before your array indexing will mean no check is generated there under any circumstances. Using D's builtin arrays (better referred to as slices) doesn't imply any necessity to use the garbage collector. You can create a slice from any memory you like, including malloc'd memory. Only appending or manually increasing .length will cause the GC to get involved. I would highly recommend them over raw pointers except in very specialised circumstances. std.container.Array is an option, but it historically hasn't been perfect. I'm not sure of the current state of affairs.
Dec 15 2014