Passing arguments a template parameters vs. function parameters
John Colvin
john.loughran.colvin at gmail.com
Tue Jun 11 14:26:34 PDT 2013
On Tuesday, 11 June 2013 at 20:46:32 UTC, Craig Dillabaugh wrote:
> I was looking at D code for constructing kd-trees, the full code
> listing for which can be found here:
>
> http://rosettacode.org/wiki/K-d_tree#Faster_Alternative_Version
>
> Of particular interest were the following functions:
>
> KdNode* makeTree(size_t dim, size_t i)(KdNode[] nodes) pure
> nothrow {
> if (!nodes.length)
> return null;
>
> auto n = findMedian!i(nodes);
> if (n != null) {
> enum i2 = (i + 1) % dim;
> immutable size_t nPos = n - nodes.ptr;
> n.left = makeTree!(dim, i2)(nodes[0 .. nPos]);
> n.right = makeTree!(dim, i2)(nodes[nPos + 1 .. $]);
> }
>
> return n;
> }
>
> // See QuickSelect method.
> KdNode* findMedian(size_t idx)(KdNode[] nodes) pure nothrow {
> auto start = nodes.ptr;
> auto end = &nodes[$ - 1] + 1;
>
> if (end <= start)
> return null;
> if (end == start + 1)
> return start;
>
> KdNode* md = start + (end - start) / 2;
>
> //clipped for sake of brevity.
> }
>
> A kd-tree is a search structure for storing multi-dimensional
> points. At each level it splits the input point set along a
> plane in one of the dimensions. In the code above this is the
> value pased as 'idx' to findMedian. findMedian finds the median
> point in the current dimension, and uses this to define the
> splitting plane for the points. At each level in the tree the
> splitting dimension is changed (which is what i/i2 is used for
> in
> makeTree()).
>
> If I had been coding this I would almost certainly have passed
> the splitting dimensions as a function parameter, since the
> compiler has to generate separate makeTree/findMedian functions
> for each dimension that i/idx takes in the program.
>
> So my question is, does anyone have any idea why the author may
> have used templates here. It was on Rosettacode so maybe they
> are
> just there to show off D's nice template abilities, but I am
> curious if in idiomatic D using templates this way is somehow
> superior to the function parameter method I would have tried.
>
> Cheers,
> Craig
It's just a trade-off between template bloat and having more
values hard-coded in for efficiency.
In this particular case, due to the use of the static array in
KdNode, if idx is known at compile time then the optimizer can go
to town on those loops in findMedian. e.g. in
foreach (p; start .. end) {
if (p.x[idx] < pivot) {
if (p != store)
swap(p.x, store.x);
store++;
}
}
given offset = p.x.offsetof + idx
p.x[idx] becomes just *(p+offset) which is fast and completely
predictable behaviour. Great for optimizers and cache prefetching
etc...
All that is meaningless guesswork though, the only thing that
will tell you for sure is benchmarking and profiling.
More information about the Digitalmars-d-learn
mailing list