July 07, 2004
On Thu, 8 Jul 2004 09:26:19 +1000, Derek <derek@psyc.ward> wrote:

[snip]
> If I really needed Ferrarri fast code, I'd drop into assembler. The Porche
> speed of D generated code is okay for me.
[snip]

Is a "Porche" a fancy french porch? My porch is attached to my house, and it's not fast at all ;o)

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 08, 2004
Norbert Nemec wrote:

> Sam McCall wrote:
> 
> 
>>Norbert Nemec wrote:
>>
>>>I don't know about Walters reasoning in that respect, but I can state my
>>>position:
>>>
>>>I think that even the opSlice that is there should be used with care. As
>>>I see it, there is no way to cleanly extend it to multiple dimensions
>>
>>Foo opSlice(int start1,end1,start2,end2,...)
>>foo[start1..end1][start2..end2]
> 
> 
> The expression
>         foo[start1..end1][start2..end2]
> does not do what you expect. It is parsed as
>         (foo[start1..end1])[start2..end2]
> where the slice resulting from the first expression is sliced again. If you
> try to handle a nested array like this, you will slice the outermost
> dimension twice.
Apologies, I did meant to type
foo[start1..end1,start2..end2]

> For true multidimensional arrays as they will hopefully be part of the
> language sometime in the future, the slicing expression would look like:
>         foo[start1..end1,start2..end2]
> Defining opSlice the way you do it would certainly be possible, but it would
> get rather ugly once you consider that you can also do partial slicing
>         foo[idx1,start2..end2]
> returning a one-dimensional array, which is different from
>         foo[idx1..idx1+1,start2..end2]
> which returns a two-dimensional array with .range[0]==1.
This is interesting, you've obviously thought about this a lot more than I have. What if there were two allowed signatures for opSlice:
T opSlice(start1,end1,...);
T opSlice(start1,end1,...,bool[N] single)
For a "full" slice (all indices are ranges), the first would be preferred, else fall back to the second with single all true.
Partial slices would only be allowed to use the second one.
In the second one, N would have to match the number of indices, and if single[i] was true then endI==startI (or startI+1, whatever), and the intent is that that dimension is being indexed, not sliced.
This is going to be a bit tricky to code for, but I think it fits with "simple things simple, hard things possible".

> If that is not ugly enough for you than consider what happens when you
> introduce striding as well:
>         foo[start1..end1:stride1,start2..end2:stride2]
Personally, I don't see this getting into slice notation, vectorisation or no. AFAICS, this is advanced/rare functionality and while I'm sure it's useful in many cases, it doesn't warrant an overload. As you say, things get ugly.

> It is not just a matter of performance but a matter of concept: what does a
> assignment to a slice actually mean. The the overloaded slicing has
> different semantics than the vectorizable slicing of arrays, then it is
> questionable whether it is a good idea to have it.
The semantics won't be exactly the same, just the same way that overriding addition for sets (union) isn't going to have the same semantics as overriding addition for numbers. While I agree that overloads of an operator should be /analagous/ (in the way iostreams aren't), I don't think a rule that says we're completely tied to what the language does is fair.
I may be misunderstanding you here.

> Currently I doubt, that
> the semantics of the vectorizable array slicing could be captured be any
> kind of a opSlice function.
I'm not sure what semantics you're referring to, again, I might have missed the point entirely.
a) the "high performance" bit: no, a class with overloads won't be as fast as the native data structure. I don't think this negates the utility.
b) slice assignment elements being reorderable: if this is imposed on native slices, it can be imposed as a condition of overloading opslice.
If the indexer of the result of the slice is inlinable (maybe if not?) then the thing should be vectorisable in a similar (but more complex) way to arrays.
c) slice assignment overwriting the original: this should be a guideline to be ignored at one's own peril ;-). Operator overloading can be abused, but we trust the programmer.
d) There being a one-to-one relationship between source cells and destination cells: being able to replace, eg, a small segment with a long segment in a string is one of the reasons I want opSliceAssign.
e) Something else... help!

> I don't think it will be possible to keep that parity. At least, any
> solution I can think of, would be too ugly to put it into D.
But it would be a pity to give it up. In java, I sometimes find myself using (native) arrays instead of (library) vectors because the syntax is better and no library can achieve it.

I agree that D should remain compatible with powerful optimisations like vectorisation, I don't think overloading slices neccesarily breaks it.
I think full slicing is a very useful feature, and even if custom slices _weren't_ vectorisable, I would argue to keep them.
If you need maximum performance, then you will always need to be careful about doing/using inefficient things. It would be ideal if opSlice wasn't one of them, but if it has to be, removing it will just mean one less feature you couldn't have used anyway. This doesn't seem like a big win to me.

Sam
July 08, 2004
Derek wrote:

> On Wed, 07 Jul 2004 23:09:27 +0200, Norbert Nemec wrote:
> Ok, so you are saying that D generates sub-optimal code for these sorts of
> applications. So don't use D! Use assembler or some specialized
> programming language. If D is to be a general purpose language, one should
> expect that it will not specialize in every programming domain.

I think, this is just for the D-community and Walter to decide: if I would feel alone on my quest to bring high-performance-numerics into D, I'd give quite soon. But I have the feeling that there is general interest for this. Obviously numerics is not so exotic after all.

The term "general purpose language" does not mean that the language should not try to excel in any special area. It just means that it should not do so on cost of the others. The amount of time, effort and complexity put into special areas is then just up to the personal interest of the language developers. In this case: Walter.

> If I really needed Ferrarri fast code, I'd drop into assembler. The Porche speed of D generated code is okay for me.

Assembler is not the way to go for really high-performance-code. The performace of modern processors depends highly on putting the instructions in the right order. Doing something like this in assembler would give complete spaghetti code. A good compiler for a good language can do much better than any programmer could do in a reasonable amount of time.

July 08, 2004
In article <miydn03kpeka$.4mtnnmprlmi5.dlg@40tude.net>, Derek says...

>If I were to reword my example above (with a pedantic streak)...
>
>Its just bloody shorthand that ensures that after the operation is complete ...
>
>   myData[4] ends up with the value 'D'
>   myData[5] ends up with the value 'e'
>   myData[6] ends up with the value 'r'
>   myData[7] ends up with the value 'e'
>   myData[8] ends up with the value 'k'
>
>And I don't really care how the magic happens.

Pretty much every language on the planet can do this. D can do this too. The statement:

#    myData[4..9] = "Derek";

does actually compile and execute correctly. But what we DON'T have is the ability to overload that expression.

I don't get why adding an opSliceAssign() overload would be a problem though. Why does anyone think it would be a problem?

Arcane Jill



July 08, 2004
On Thu, 8 Jul 2004 07:14:00 +0000 (UTC), Arcane Jill wrote:

> In article <miydn03kpeka$.4mtnnmprlmi5.dlg@40tude.net>, Derek says...
> 
>>If I were to reword my example above (with a pedantic streak)...
>>
>>Its just bloody shorthand that ensures that after the operation is complete ...
>>
>>   myData[4] ends up with the value 'D'
>>   myData[5] ends up with the value 'e'
>>   myData[6] ends up with the value 'r'
>>   myData[7] ends up with the value 'e'
>>   myData[8] ends up with the value 'k'
>>
>>And I don't really care how the magic happens.
> 
> Pretty much every language on the planet can do this. D can do this too. The statement:
> 
> #    myData[4..9] = "Derek";
> 
> does actually compile and execute correctly. But what we DON'T have is the ability to overload that expression.

That's why I started this thread. I assumed it was overloadable but soon found out otherwise. It's only an operator overload which means we can use function call syntax instead. That is what I'm doing now, BTW.

    void opSlice(int i, int j, whatever x) { . . .  }

and using it thus...

    Foo.opSlice(i,j,x);

instead of the more obvious

    Foo[i,j] = x;

> I don't get why adding an opSliceAssign() overload would be a problem though. Why does anyone think it would be a problem?

Beats me!

-- 
Derek
Melbourne, Australia
8/Jul/04 5:28:45 PM
July 08, 2004
In article <ccioo4$dj6$1@digitaldaemon.com>, Norbert Nemec says...

>Assembler is not the way to go for really high-performance-code. The performace of modern processors depends highly on putting the instructions in the right order. Doing something like this in assembler would give complete spaghetti code. A good compiler for a good language can do much better than any programmer could do in a reasonable amount of time.

Forgive my language, but I can't figure how better to express this...

Bollocks!

I can do better in assembler than any C, C++ or D compiler I have ever met. I think you're going to need some hard evidence to back up the above assertion. Either that, or maybe set a competition - assember-written-by-human versus assembler-compiled-from-C/C++/D-written-by human. But what would we get as a prize?

Jill


July 08, 2004
Arcane Jill wrote:

> I don't get why adding an opSliceAssign() overload would be a problem though. Why does anyone think it would be a problem?

I just thought it was, but I changed my mind after I found that idea of opPartialIndex. See the other thread about the full concept.

July 08, 2004
Arcane Jill wrote:

> In article <ccioo4$dj6$1@digitaldaemon.com>, Norbert Nemec says...
> 
>>Assembler is not the way to go for really high-performance-code. The performace of modern processors depends highly on putting the instructions in the right order. Doing something like this in assembler would give complete spaghetti code. A good compiler for a good language can do much better than any programmer could do in a reasonable amount of time.
> 
> Forgive my language, but I can't figure how better to express this...
> 
> Bollocks!
> 
> I can do better in assembler than any C, C++ or D compiler I have ever met. I think you're going to need some hard evidence to back up the above assertion. Either that, or maybe set a competition - assember-written-by-human versus assembler-compiled-from-C/C++/D-written-by human. But what would we get as a prize?

I can show you a piece of C-code I wrote for a class in High-Performance-Computing: red-black-relaxation.

We started out with a fairly simple algorithm: Four nested loops iterating over the same array over and over again. Over the course of one semester, we improved this code step by reordering, interlacing and partially unrolling the loops. The algorithm stayed the same, only the ordering of the commands was changed. In the end, the code (initially ~20 simple lines) had grown to several hundred lines of highly complex code, running roughly 10 times as fast.

Handling this kind of code in C is complex but possible, in Assembler, you could probably forget about it. A good compiler for a well-designed language would have been able to do all the steps of instruction reordering automatically and intelligently. In C/C++/D, this is not possible yet, because the language is not designed for it.

Currently, such languages and compilers are still in the experimental stage (see www.sac-home.org, for example). My intention is to bring the crucial language elements into D now, so that tomorrows compilers have a chance to optimize. Of course, this should happen without sacrificing the general qualities of D.

If you are interested in seeing the code, I can try to dig it up and bring it to a presentable shape. Will take some time, though.
July 08, 2004
Arcane Jill wrote:

> I don't get why adding an opSliceAssign() overload would be a problem though.
> Why does anyone think it would be a problem?
Agree with you, I don't see any problem at all.
The current situation strikes me as a borderline-bug.
Sam
July 08, 2004
In article <ccivu1$pgc$1@digitaldaemon.com>, Norbert Nemec says...

>If you are interested in seeing the code, I can try to dig it up and bring it to a presentable shape. Will take some time, though.

Well, there's "interested" and there's "having time". Personally I would *love* to take on a head-to-head optimization challenge - my assembler versus your compiled C. But, I am just too busy right now. I have things to do that are more important than my pride.

But one day, when I'm less busy (Free time? What's that?), I'll take you up on that challenge. And to make it interesting, the loser buys the winner a Guinness, yes?

Jill