digitalmars.D - Ideas from the Chapel language
- bearophile (22/22) Oct 03 2007 The Cray Inc is designing the Chapel Language:
- Bruce Adams (3/10) Oct 03 2007 swap is very useful especially in exception safe programming.
- Sean Kelly (6/17) Oct 03 2007 Certainly. But how much of a need is there for swap in a
- Derek Parnell (18/30) Oct 03 2007 Isn't a simple template such this sufficient?
- Bruce Adams (15/51) Oct 03 2007 Most of the time it is.
- Gregor Richards (17/48) Oct 03 2007 For the ridiculously-insane:
- David Brown (15/29) Oct 03 2007 And rather devestating if another thread causes a garbage collection.
- Bruce Adams (8/46) Oct 04 2007 I think this is very much implementation defined.
- Bill Baxter (9/58) Oct 04 2007 I find it hard to believe that a compiler couldn't recognize that this
- Derek Parnell (9/17) Oct 04 2007 Maybe it could, but that's not the point of a programming language. A
- renoX (7/22) Oct 04 2007 Uh? If 'swap(a,b)' is ok, then you put swap as a function call, that the...
- Bill Baxter (6/21) Oct 04 2007 Right, so you put those three lines in a template function called
- BCS (3/23) Oct 03 2007 swap!(byte)(a, b)
The Cray Inc is designing the Chapel Language: http://chapel.cs.washington.edu/ The following notes are from the specification V. 0.750: http://chapel.cs.washington.edu/spec-0.750.pdf I think it's rather cute, it looks like a cross between C++, Fortress and Python. Here are few things I think can be interesting for D designers too: - Chap. 5.4.2 page 13, ranges with "by stride". - Chap. 5.5 page 18, if expression look more readable: var half = if (i % 2) then i/2 +1 else i/2; Instead of: auto half = (i % 2) ? i/2 +1 : i/2; - Chap. 5.7, page 23, Iterators (they look like copied from Python) - Chap. 5.8, page 23, file I/O, seems better (it looks like copied from Python) - Chap. 11.5 page 65, swap operator (useful but probably not enough to justify a new operator) - Chap. 11.9.1, 11.9.2 page 68, zipper/tensor iteration (partially copied from Python) - Chap. 17.5 page 96, Tuple Destructuring (looking like copied from Python) - Chap. 18.1-18.5 page 99-103, stridable Ranges, Unbounded Range Literals, RangeAssignment, Range methods, etc. - Chap. 19, page 105, Domains seem interesting too (Chap. 19.9 is about subdomains). - Chap. 20, page 121, more on iterators. - Chap. 22, page 131, forall, ordered forall, cobegin, coforall, serial, etc. - Chap. 24.1, page 143, Reduction Expressions Bye, bearophile
Oct 03 2007
bearophile Wrote:The Cray Inc is designing the Chapel Language: http://chapel.cs.washington.edu/ The following notes are from the specification V. 0.750: http://chapel.cs.washington.edu/spec-0.750.pdf I think it's rather cute, it looks like a cross between C++, Fortress and Python. Here are few things I think can be interesting for D designers too: - Chap. 11.5 page 65, swap operator (useful but probably not enough to justify a new operator)swap is very useful especially in exception safe programming. I would like to see swap used as the default implementation of D's transfer constructor (and C++0x's forthcoming move constructor)
Oct 03 2007
Bruce Adams wrote:bearophile Wrote:Certainly. But how much of a need is there for swap in a reference-based language like D? I would think that most swaps would simply operate on references. Unless you're talking about structs, and structs do not have copy ctors so there is little risk of an exception. SeanThe Cray Inc is designing the Chapel Language: http://chapel.cs.washington.edu/ The following notes are from the specification V. 0.750: http://chapel.cs.washington.edu/spec-0.750.pdf I think it's rather cute, it looks like a cross between C++, Fortress and Python. Here are few things I think can be interesting for D designers too: - Chap. 11.5 page 65, swap operator (useful but probably not enough to justify a new operator)swap is very useful especially in exception safe programming.
Oct 03 2007
On Wed, 03 Oct 2007 14:53:57 -0400, Bruce Adams wrote:bearophile Wrote:Isn't a simple template such this sufficient? template swap(TYPE) { void swap(ref TYPE a, ref TYPE b) { synchronized { TYPE temp = a; a = b; b = temp; } } } -- Derek Parnell Melbourne, Australia skype: derek.j.parnellThe Cray Inc is designing the Chapel Language: http://chapel.cs.washington.edu/ The following notes are from the specification V. 0.750: http://chapel.cs.washington.edu/spec-0.750.pdf I think it's rather cute, it looks like a cross between C++, Fortress and Python. Here are few things I think can be interesting for D designers too: - Chap. 11.5 page 65, swap operator (useful but probably not enough to justify a new operator)swap is very useful especially in exception safe programming. I would like to see swap used as the default implementation of D's transfer constructor (and C++0x's forthcoming move constructor)
Oct 03 2007
Derek Parnell Wrote:On Wed, 03 Oct 2007 14:53:57 -0400, Bruce Adams wrote:Most of the time it is. Sometimes swapping references is sufficient but sometimes you actually want real data to change. As the type gets bigger you start to prefer decomposing swap into swaps of individual members rather than 2 whole copes. Do you really want to copy 120Mb twice? Actually you should decomposing the swap from the outset if possible (second to swapping just references if possible obviously). Swaps also have to be atomic and never throw exceptions. A more advanced template might use tuples recursively to do this. I would want that in the standard library. Some hardware platforms may support swaps directly. In reversible computing (okay so no-one in the real world uses that - yet) it is a fundamental operation. Then it becomes a compiler decision how best to implement it. If it is used as the default implementation for transfer constructors this goes double. I suspect a standard library implementation is sufficient from the outset leaving it up to the compiler vendor to decide how clever he or she needs to be. It continues to suprise me that we don't prefer swap to destructive assignment more generally. Perhaps it feels less natural after years of the C way? Bruce.bearophile Wrote:Isn't a simple template such this sufficient? template swap(TYPE) { void swap(ref TYPE a, ref TYPE b) { synchronized { TYPE temp = a; a = b; b = temp; } } } -- Derek Parnell Melbourne, Australia skype: derek.j.parnellThe Cray Inc is designing the Chapel Language: http://chapel.cs.washington.edu/ The following notes are from the specification V. 0.750: http://chapel.cs.washington.edu/spec-0.750.pdf I think it's rather cute, it looks like a cross between C++, Fortress and Python. Here are few things I think can be interesting for D designers too: - Chap. 11.5 page 65, swap operator (useful but probably not enough to justify a new operator)swap is very useful especially in exception safe programming. I would like to see swap used as the default implementation of D's transfer constructor (and C++0x's forthcoming move constructor)
Oct 03 2007
Derek Parnell wrote:On Wed, 03 Oct 2007 14:53:57 -0400, Bruce Adams wrote:For the ridiculously-insane: void swap(T)(ref T a, ref T b) { synchronized { // this should be some kind of static for ... for (size_t i = 0; i < (a.sizeof/size_t.sizeof); i++) { (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; (cast(size_t*) &b)[i] = (cast(size_t*) &a)[i] ^ (cast(size_t*) &b)[i]; (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; } } } Add some loop unrolling and that's more efficient than memcpy :P - Gregor Richards PS: /me <3 XOR swappingbearophile Wrote:Isn't a simple template such this sufficient? template swap(TYPE) { void swap(ref TYPE a, ref TYPE b) { synchronized { TYPE temp = a; a = b; b = temp; } } }The Cray Inc is designing the Chapel Language: http://chapel.cs.washington.edu/ The following notes are from the specification V. 0.750: http://chapel.cs.washington.edu/spec-0.750.pdf I think it's rather cute, it looks like a cross between C++, Fortress and Python. Here are few things I think can be interesting for D designers too: - Chap. 11.5 page 65, swap operator (useful but probably not enough to justify a new operator)swap is very useful especially in exception safe programming. I would like to see swap used as the default implementation of D's transfer constructor (and C++0x's forthcoming move constructor)
Oct 03 2007
On Wed, Oct 03, 2007 at 06:25:08PM -0700, Gregor Richards wrote:For the ridiculously-insane: void swap(T)(ref T a, ref T b) { synchronized { // this should be some kind of static for ... for (size_t i = 0; i < (a.sizeof/size_t.sizeof); i++) { (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; (cast(size_t*) &b)[i] = (cast(size_t*) &a)[i] ^ (cast(size_t*) &b)[i]; (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; } } } Add some loop unrolling and that's more efficient than memcpy :PAnd rather devestating if another thread causes a garbage collection. Doesn't the synchronized just lock this section of code, not the whole program? But, why would it be any more efficient than the inside of the loop just saying: size_t tmp = ((cast(size_t*) &a)[i]; ((cast(size_t*) &a)[i] = ((cast(size_t*) &b)[i]; ((cast(size_t*) &b)[i] = tmp; This does 2 reads and 2 writes. The xor version does 4 reads and 3 writes. How could it be faster? The xor trick really only helps you if you are one architecture where you don't have a register to spare. Shuffling through a register is going to be much faster than multiple reads and writes to memory. David
Oct 03 2007
David Brown Wrote:On Wed, Oct 03, 2007 at 06:25:08PM -0700, Gregor Richards wrote:I think this is very much implementation defined. If you are operating on a block of memory rather than data small enough to fit in a register you have to dereference memory anyway. And lets not forget platforms with some sort of exchange registers as a primative operation. Though, I dislike joining the army of people rushing to suggest adding more and more (often unnecessary) features to an already feature rich language, I think that it is implementation defined justifies it being a low level operator implemented by the compiler. Swap is primative enough to have an unambiguous meaning and unlikely to confuse noobs. I'd very much like to hear what a (the) compiler writer has to say on the subject (especially in light of transfer constructors). I wonder if Walter is reading? Regards, Bruce.For the ridiculously-insane: void swap(T)(ref T a, ref T b) { synchronized { // this should be some kind of static for ... for (size_t i = 0; i < (a.sizeof/size_t.sizeof); i++) { (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; (cast(size_t*) &b)[i] = (cast(size_t*) &a)[i] ^ (cast(size_t*) &b)[i]; (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; } } } Add some loop unrolling and that's more efficient than memcpy :PAnd rather devestating if another thread causes a garbage collection. Doesn't the synchronized just lock this section of code, not the whole program? But, why would it be any more efficient than the inside of the loop just saying: size_t tmp = ((cast(size_t*) &a)[i]; ((cast(size_t*) &a)[i] = ((cast(size_t*) &b)[i]; ((cast(size_t*) &b)[i] = tmp; This does 2 reads and 2 writes. The xor version does 4 reads and 3 writes. How could it be faster? The xor trick really only helps you if you are one architecture where you don't have a register to spare. Shuffling through a register is going to be much faster than multiple reads and writes to memory. David
Oct 04 2007
Bruce Adams wrote:David Brown Wrote:I find it hard to believe that a compiler couldn't recognize that this is a swap operation: tmp = a; a = b; b = tmp; If it's not harder than I think for some reason, then it's not really needed in the language. --bbOn Wed, Oct 03, 2007 at 06:25:08PM -0700, Gregor Richards wrote:I think this is very much implementation defined. If you are operating on a block of memory rather than data small enough to fit in a register you have to dereference memory anyway. And lets not forget platforms with some sort of exchange registers as a primative operation. Though, I dislike joining the army of people rushing to suggest adding more and more (often unnecessary) features to an already feature rich language, I think that it is implementation defined justifies it being a low level operator implemented by the compiler. Swap is primative enough to have an unambiguous meaning and unlikely to confuse noobs. I'd very much like to hear what a (the) compiler writer has to say on the subject (especially in light of transfer constructors). I wonder if Walter is reading? Regards, Bruce.For the ridiculously-insane: void swap(T)(ref T a, ref T b) { synchronized { // this should be some kind of static for ... for (size_t i = 0; i < (a.sizeof/size_t.sizeof); i++) { (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; (cast(size_t*) &b)[i] = (cast(size_t*) &a)[i] ^ (cast(size_t*) &b)[i]; (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; } } } Add some loop unrolling and that's more efficient than memcpy :PAnd rather devestating if another thread causes a garbage collection. Doesn't the synchronized just lock this section of code, not the whole program? But, why would it be any more efficient than the inside of the loop just saying: size_t tmp = ((cast(size_t*) &a)[i]; ((cast(size_t*) &a)[i] = ((cast(size_t*) &b)[i]; ((cast(size_t*) &b)[i] = tmp; This does 2 reads and 2 writes. The xor version does 4 reads and 3 writes. How could it be faster? The xor trick really only helps you if you are one architecture where you don't have a register to spare. Shuffling through a register is going to be much faster than multiple reads and writes to memory. David
Oct 04 2007
On Thu, 04 Oct 2007 17:55:05 +0900, Bill Baxter wrote:I find it hard to believe that a compiler couldn't recognize that this is a swap operation: tmp = a; a = b; b = tmp; If it's not harder than I think for some reason, then it's not really needed in the language.Maybe it could, but that's not the point of a programming language. A programming language is for people, not computers, to read. It is whole lot easy to recognise "swap(a,b)" or even "a<->b" as a swapping operation than three lines of code. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Oct 04 2007
Derek Parnell a écrit :On Thu, 04 Oct 2007 17:55:05 +0900, Bill Baxter wrote:Uh? If 'swap(a,b)' is ok, then you put swap as a function call, that the compiler inline, or as a macro if you want to be sure that it will be inlined. As for an operator, given that I don't remember the last time that I needed to swap variables, I would vote against it. renoXI find it hard to believe that a compiler couldn't recognize that this is a swap operation: tmp = a; a = b; b = tmp; If it's not harder than I think for some reason, then it's not really needed in the language.Maybe it could, but that's not the point of a programming language. A programming language is for people, not computers, to read. It is whole lot easy to recognise "swap(a,b)" or even "a<->b" as a swapping operation than three lines of code.
Oct 04 2007
Derek Parnell wrote:On Thu, 04 Oct 2007 17:55:05 +0900, Bill Baxter wrote:Right, so you put those three lines in a template function called "swap". If the compiler can recognize that's exchanging the values of a and b, then there's no need for swap to be a compiler intrinsic. The plain old function is good enough. --bbI find it hard to believe that a compiler couldn't recognize that this is a swap operation: tmp = a; a = b; b = tmp; If it's not harder than I think for some reason, then it's not really needed in the language.Maybe it could, but that's not the point of a programming language. A programming language is for people, not computers, to read. It is whole lot easy to recognise "swap(a,b)" or even "a<->b" as a swapping operation than three lines of code.
Oct 04 2007
Reply to Gregor,For the ridiculously-insane: void swap(T)(ref T a, ref T b) { synchronized { // this should be some kind of static for ... for (size_t i = 0; i < (a.sizeof/size_t.sizeof); i++) { (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; (cast(size_t*) &b)[i] = (cast(size_t*) &a)[i] ^ (cast(size_t*) &b)[i]; (cast(size_t*) &a)[i] ^= (cast(size_t*) &b)[i]; } } } Add some loop unrolling and that's more efficient than memcpy :P - Gregor Richards PS: /me <3 XOR swappingswap!(byte)(a, b) swap!(byte[5])(a, b)
Oct 03 2007