digitalmars.D - Array operations -- not actually so difficult
- Don Clugston (33/33) Dec 15 2006 Array operations are one of the very few 2.0 features that haven't made
- Nox / Lux (5/8) Dec 15 2006 Hmm, speaking of array operations and dot product ... Seeing as this (do...
- Charlie (6/16) Dec 15 2006 I think this is the main reason why it hasn't been implemented yet ?
- Don Clugston (5/15) Dec 15 2006 Since DMD has not support for 64 bit yet, and AFAIK none is planned yet,...
- Bill Baxter (5/28) Dec 15 2006 How does that result in the above code for dot product?
- Sean Kelly (91/119) Dec 15 2006 Not necessarily. Consider:
- Bill Baxter (4/155) Dec 15 2006 I put it on my D Rants page[1], but I don't think I ever filed it as a b...
- Kirk McDonald (19/24) Dec 15 2006 On that page:
- Bill Baxter (6/34) Dec 15 2006 That's interesting. Didn't know that. Seems not as intuitive as
- Don Clugston (7/35) Dec 16 2006 I've posted an update to my expression templates code in
- =?iso-8859-1?q?Knud_S=F8rensen?= (18/57) Dec 15 2006 I expect for the array operation in 2.0 is something like vectorization.
- Don Clugston (6/25) Dec 16 2006 This doesn't generate temporary arrays either. The point is, that with
- Stewart Gordon (11/19) Dec 16 2006 I've never properly got my head around this expression templates
Array operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all. Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c); For performance, it would be better if the compiler actually *didn't* evaluate a+b. Instead, that should compile to: real sum = 0; for (int i=0; i<c.length; ++i) { sum+=(a[i]+b[i])*c[i]; } d=sum; In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work. ---------- void opMulAssign(real [] a, real w) { for(int i=0; i<a.length; ++i) { a[i]*=w; } } void main() { real b[] = [1.0L, 2, 3, 4]; b.opMulAssign(3.5); // OK. b *= 3.5; // Fails with "Error: 'b' is not a scalar, it is a real[]" } ---------- So the message to Walter is, support for array operations will not require any change to the back end. They are just a bit of syntactic sugar at the front end.
Dec 15 2006
Don Clugston wrote:Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c);Hmm, speaking of array operations and dot product ... Seeing as this (dot product) is one of the added instructions of the upcoming SSE4, would it be possible to automatically make use of this instruction behind the scenes, compiling a normal version only if SSE4 is not supported?
Dec 15 2006
Nox / Lux wrote:Don Clugston wrote:I think this is the main reason why it hasn't been implemented yet ? The backend can pull some tricks to optimize certain operations. I would certainly like to see array ops implemented though, maybe this can be a 1.0 solution, and re-written for 2.0 ? CharlieConsider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c);Hmm, speaking of array operations and dot product ... Seeing as this (dot product) is one of the added instructions of the upcoming SSE4, would it be possible to automatically make use of this instruction behind the scenes, compiling a normal version only if SSE4 is not supported?
Dec 15 2006
Nox / Lux wrote:Don Clugston wrote:Since DMD has not support for 64 bit yet, and AFAIK none is planned yet, I think it will be a very long time before SSE4 is supported. But, it should be possible to link to BLAS routines that make use of the new instructions.Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c);Hmm, speaking of array operations and dot product ... Seeing as this (dot product) is one of the added instructions of the upcoming SSE4, would it be possible to automatically make use of this instruction behind the scenes, compiling a normal version only if SSE4 is not supported?
Dec 15 2006
Don Clugston wrote:Array operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all. Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c); For performance, it would be better if the compiler actually *didn't* evaluate a+b. Instead, that should compile to: real sum = 0; for (int i=0; i<c.length; ++i) { sum+=(a[i]+b[i])*c[i]; } d=sum; In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work.How does that result in the above code for dot product? Looks to me like if all you have is calling opXXX functions the above dot would still become two loops with a tmp for the a+b. --bb
Dec 15 2006
Bill Baxter wrote:Don Clugston wrote:Not necessarily. Consider: struct AddExp(T, U) { T lhs; U rhs; static AddExp!(T,U) opCall( T lhs, U rhs ) in { assert( lhs.length == rhs.length ); assert( is( typeof(T[0]) == typeof(U[0]) ) ); } body { AddExp!(T,U) exp; exp.lhs = lhs; exp.rhs = rhs; return exp; } typeof(T[0]) opIndex( size_t i ) { return lhs[i] + rhs[i]; } typeof(T[0])[] opSlice( size_t b, size_t e ) { typeof(T[0])[] sum = new typeof(T[0])[lhs.length]; for( size_t i = 0; i < lhs.length; ++i ) { sum[i] = lhs[i] + rhs[i]; } return sum; } size_t length() { return lhs.length; } } AddExp!(T,U) opAdd(T, U)( T lhs, U rhs ) { return AddExp!(T,U)( lhs, rhs ); } T[] opAssign(T, U)( inout T[] lhs, U rhs ) in { assert( is( typeof(T[0]) == typeof(U[0]) ) ); } body { lhs = rhs[0 .. $]; return lhs; } real dotp(T,U)( T lhs, U rhs ) { real sum = 0.0; assert( lhs.length == rhs.length ); for( size_t i = 0; i < lhs.length; ++i ) { sum += lhs[i] * rhs[i]; } return sum; } void main() { real[] a, b, c; a ~= 1.0; a ~= 2.0; b ~= 3.0; b ~= 4.0; c ~= 5.0; c ~= 6.0; // test opSlice auto s = opAdd( a, b ); real[] r = s[0 .. s.length]; for( size_t i = 0; i < r.length; ++i ) { printf( "%Lf = %Lf\n", r[i], s[i] ); } // compound expression real res = dotp( opAdd( a, b ), c ); printf( "\n%Lf\n", res ); } prints: 4.000000 = 4.000000 6.000000 = 6.000000 56.000000 Thanks to the wonder of templates, a properly designed expression struct could be evaluated as-is rather than needing to be converted to an array before being passed to dotp(). If we were able to define free-floating operators as per Don's suggestion, the above would be darn slick :-) By the way, I originally tried slicing using the standard syntax "s[0 .. $]" and got this error: test.d(84): Error: undefined identifier __dollar I imagine this is a known issue? SeanArray operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all. Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c); For performance, it would be better if the compiler actually *didn't* evaluate a+b. Instead, that should compile to: real sum = 0; for (int i=0; i<c.length; ++i) { sum+=(a[i]+b[i])*c[i]; } d=sum; In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work.How does that result in the above code for dot product? Looks to me like if all you have is calling opXXX functions the above dot would still become two loops with a tmp for the a+b.
Dec 15 2006
Sean Kelly wrote:Bill Baxter wrote:I put it on my D Rants page[1], but I don't think I ever filed it as a bug. [1] http://www.prowiki.org/wiki4d/wiki.cgi?BillBaxter --bbDon Clugston wrote:Not necessarily. Consider: struct AddExp(T, U) { T lhs; U rhs; static AddExp!(T,U) opCall( T lhs, U rhs ) in { assert( lhs.length == rhs.length ); assert( is( typeof(T[0]) == typeof(U[0]) ) ); } body { AddExp!(T,U) exp; exp.lhs = lhs; exp.rhs = rhs; return exp; } typeof(T[0]) opIndex( size_t i ) { return lhs[i] + rhs[i]; } typeof(T[0])[] opSlice( size_t b, size_t e ) { typeof(T[0])[] sum = new typeof(T[0])[lhs.length]; for( size_t i = 0; i < lhs.length; ++i ) { sum[i] = lhs[i] + rhs[i]; } return sum; } size_t length() { return lhs.length; } } AddExp!(T,U) opAdd(T, U)( T lhs, U rhs ) { return AddExp!(T,U)( lhs, rhs ); } T[] opAssign(T, U)( inout T[] lhs, U rhs ) in { assert( is( typeof(T[0]) == typeof(U[0]) ) ); } body { lhs = rhs[0 .. $]; return lhs; } real dotp(T,U)( T lhs, U rhs ) { real sum = 0.0; assert( lhs.length == rhs.length ); for( size_t i = 0; i < lhs.length; ++i ) { sum += lhs[i] * rhs[i]; } return sum; } void main() { real[] a, b, c; a ~= 1.0; a ~= 2.0; b ~= 3.0; b ~= 4.0; c ~= 5.0; c ~= 6.0; // test opSlice auto s = opAdd( a, b ); real[] r = s[0 .. s.length]; for( size_t i = 0; i < r.length; ++i ) { printf( "%Lf = %Lf\n", r[i], s[i] ); } // compound expression real res = dotp( opAdd( a, b ), c ); printf( "\n%Lf\n", res ); } prints: 4.000000 = 4.000000 6.000000 = 6.000000 56.000000 Thanks to the wonder of templates, a properly designed expression struct could be evaluated as-is rather than needing to be converted to an array before being passed to dotp(). If we were able to define free-floating operators as per Don's suggestion, the above would be darn slick :-) By the way, I originally tried slicing using the standard syntax "s[0 .. $]" and got this error: test.d(84): Error: undefined identifier __dollar I imagine this is a known issue? SeanArray operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all. Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c); For performance, it would be better if the compiler actually *didn't* evaluate a+b. Instead, that should compile to: real sum = 0; for (int i=0; i<c.length; ++i) { sum+=(a[i]+b[i])*c[i]; } d=sum; In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work.How does that result in the above code for dot product? Looks to me like if all you have is calling opXXX functions the above dot would still become two loops with a tmp for the a+b.
Dec 15 2006
Bill Baxter wrote:I put it on my D Rants page[1], but I don't think I ever filed it as a bug. [1] http://www.prowiki.org/wiki4d/wiki.cgi?BillBaxter --bbOn that page: ----- It should be possible to set the init property for a typedef'ed or other user defined type. E.g. typedef int myint; myint.init = -1; ----- You can do this: import std.stdio; typedef int INT = 20; void main() { INT i; writefln(i); // prints 20 } -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Dec 15 2006
Kirk McDonald wrote:Bill Baxter wrote:That's interesting. Didn't know that. Seems not as intuitive as setting .init directly, but now that I think about it, I guess there are issues with allowing the init value to be set anywhere other that at the point of type definition. --bbI put it on my D Rants page[1], but I don't think I ever filed it as a bug. [1] http://www.prowiki.org/wiki4d/wiki.cgi?BillBaxter --bbOn that page: ----- It should be possible to set the init property for a typedef'ed or other user defined type. E.g. typedef int myint; myint.init = -1; ----- You can do this: import std.stdio; typedef int INT = 20; void main() { INT i; writefln(i); // prints 20 }
Dec 15 2006
Bill Baxter wrote:Don Clugston wrote:I've posted an update to my expression templates code in dsource/mathextra/Blade. It prints near-optimal x87 asm code for any combination of +,-,+=,-=, *, *= and dot product on double[] vectors. The code is still less than 300 lines, so a comprehensive expression template system would probably not be too horrible.Array operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all. Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c); For performance, it would be better if the compiler actually *didn't* evaluate a+b. Instead, that should compile to: real sum = 0; for (int i=0; i<c.length; ++i) { sum+=(a[i]+b[i])*c[i]; } d=sum; In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work.How does that result in the above code for dot product? Looks to me like if all you have is calling opXXX functions the above dot would still become two loops with a tmp for the a+b.
Dec 16 2006
I expect for the array operation in 2.0 is something like vectorization. see http://www.all-technology.com/eigenpolls/dwishlist/index.php?it=10 Which allows you (in one line) to make multidimensional calculations on an arbitrary number of multidimensional arrays, but it still allows you to read exactly which indexed is used and the exact calculation performed. The syntax don't generate temporary arrays and allow the compiler to freely reorder nested loops. Also the compiler will be free to support for SSE? and GPUs in the future without your having to rewriting the vectorization code. I don't expect to see this in 1.0 I am just pointing out that the array operation you suggest here seems fare from my expectations for 2.0. Knud On Fri, 15 Dec 2006 10:40:16 +0100, Don Clugston wrote:Array operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all. Consider something like a dot product, real a[], b[], c[]; real d = dot(a+b, c); For performance, it would be better if the compiler actually *didn't* evaluate a+b. Instead, that should compile to: real sum = 0; for (int i=0; i<c.length; ++i) { sum+=(a[i]+b[i])*c[i]; } d=sum; In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work. ---------- void opMulAssign(real [] a, real w) { for(int i=0; i<a.length; ++i) { a[i]*=w; } } void main() { real b[] = [1.0L, 2, 3, 4]; b.opMulAssign(3.5); // OK. b *= 3.5; // Fails with "Error: 'b' is not a scalar, it is a real[]" } ---------- So the message to Walter is, support for array operations will not require any change to the back end. They are just a bit of syntactic sugar at the front end.
Dec 15 2006
Knud Sørensen wrote:I expect for the array operation in 2.0 is something like vectorization. see http://www.all-technology.com/eigenpolls/dwishlist/index.php?it=10 Which allows you (in one line) to make multidimensional calculations on an arbitrary number of multidimensional arrays, but it still allows you to read exactly which indexed is used and the exact calculation performed. The syntax don't generate temporary arrays and allow the compiler to freely reorder nested loops.This doesn't generate temporary arrays either. The point is, that with this bit of syntax sugar, we could use expression templates to do virtually all of this stuff. Vectorisation is notoriously difficult for compilers to do well without help; this is an easy way of assisting the compiler.Also the compiler will be free to support for SSE? and GPUs in the future without your having to rewriting the vectorization code. I don't expect to see this in 1.0 I am just pointing out that the array operation you suggest here seems fare from my expectations for 2.0.Knud
Dec 16 2006
Don Clugston wrote:Array operations are one of the very few 2.0 features that haven't made it into 1.0. My experiments into expression templates suggest that it might not be very complicated after all.I've never properly got my head around this expression templates business. Maybe I just need to read up on it a bit more. <snip>In fact, we could create a fantastic library implementation of array operations with a tiny bit of syntactic sugar: instead of generating an error message for array operations, look for an opXXX function, and treat it the same way the implicit array properties work.<snip> True. Having array operations built in would create plenty of optimisation potential, but having a library implementation with the help of a bit of syntactic sugar at the language level would at least work. How many of you have seen my proposal from a while back? http://www.digitalmars.com/d/archives/digitalmars/D/16647.html Stewart.
Dec 16 2006