January 03, 2012
"Walter Bright" <newshound2@digitalmars.com> wrote in message news:jdvgnr$2uer$1@digitalmars.com...
> On 1/3/2012 12:48 AM, Nick Sabalausky wrote:
>> "Could an omnipotent being make a
>> rock that isn't a rock?"
>
> I don't know, but I'm sure he could make a product that is both a floor wax and a dessert topping.

I'm having visions of Billy Mays...


January 03, 2012
On Fri, 30 Dec 2011 06:51:44 +0100, Vladimir Panteleev <vladimir@thecybershadow.net> wrote:

> On Thursday, 29 December 2011 at 19:47:39 UTC, Walter Bright wrote:
>> On 12/29/2011 3:19 AM, Vladimir Panteleev wrote:
>>> I'd like to invite you to translate Daniel Vik's C memcpy implementation to D:
>>> http://www.danielvik.com/2010/02/fast-memcpy-in-c.html
>>
>> Challenge accepted.
>
> Ah, a direct translation using functions! This is probably the most elegant approach, however - as I'm sure you've noticed - the programmer has no control over what gets inlined.
>
>> Examining the assembler output, it inlines everything except COPY_SHIFT, COPY_NO_SHIFT, and COPY_REMAINING. The inliner in dmd could definitely be improved, but that is not a problem with the language, but the implementation.
>
> This is the problem with heuristic inlining: while great by itself, in a position such as this the programmer is left with no choice but to examine the assembler output to make sure the compiler does what the programmer wants it to do. Such behavior can change from one implementation to another, and even from one compiler version to another. (After all, I don't think that we can guarantee that what's inlined today, will be inlined tomorrow.)
>
For real performance bottlenecks one should always examine the assembly.
For most code inlining hardly ever matters for the runtime of your
program and focusing on efficient algorithms is most important.

What really baffles me is that people want control over inlining
but nobody seems to ever have noticed that x64 switch doesn't switch
and x64 vector ops aren't vectorized. Both of which are really
important in performance sensitive code.

>> Continuing in that vein, please note that neither C nor C++ require inlining of any sort. The "inline" keyword is merely a hint to the compiler. What inlining takes place is completely implementation defined, not language defined.
>
> I think we can agree that the C inline hint is of limited use. However, major C compiler vendors implement an extension to force inlining. Generally, I would say that common vendor extensions seen in other languages are an opportunity for D to avoid a similar mess: such extensions would not have to be required to be implemented, but when they are, they would use the same syntax across implementations.
>
>> I wish to note that the D version semantically accomplishes the same thing as the C version without using mixins or CTFE - it's all straightforward code, without the abusive preprocessor tricks.
>
> I don't think there's much value in that statement. After all, except for a few occasional templates (which weren't strictly necessary), your translation uses few D-specific features. If you were to leave yourself at the mercy of a C compiler's optimizer, your rewrite would merely be a testament against C macros, not the power of D.
>
> However, the most important part is: this translation is incorrect. C macros in the original code provide a guarantee that the code is inlined. D cannot make such guarantees - even your amended version is tuned to one specific implementation (and possibly, only a specific range of versions of it).
January 03, 2012
On Tue, Jan 3, 2012 at 2:36 AM, maarten van damme <maartenvd1994@gmail.com>wrote:

> there is no destruction/creation going on, energy is constant at all times
> in a closed system. That's how I thought about it :)
> If it's constant anyway he wouldn't have to bother with a gc, would he?
>
I see. Something like "Matter is neither created nor destroyed...".

But similarly memory is neither created nor destroyed. Unless of course you're talking about a  god language that can create hardware at run-time:

// make sure the power supply can handle the extra memory
this.PowerSupply.currentCurrent()++;

// ... don't forget extra bypass capacitance
// and check the wiring just in case.
Capacitor mycap =  new Capacitor(0.47uF);
this.PowerSupply.BypassCap.Add(mycap);
assert(this.PowerSupply.PositiveRail..capacity > 2.1A);
assert(this.PowerSupply.NegativeRail..capacity > 2.1A);


// finally! Add the extra storage we need
this.SDRAM.extend(1GB);


>I meant he can invent a task he will never be able to solve. ;)
> this seems rather strange doesn't it?
> If something is able to do everything, he should be able to invent
> something he is not able to do. if he invented something he is not able to
> do, he can't do everything.
> One could therefore assume it is not possible to be able to do everything
> :D
>

Can an omnipotent being bypass logical syllogisms? Don't forget: *ALL* powerful means not just the physical stuff.

If so, then your argument doesn't hold... or it does.  More precisely, it holds and doesn't hold at the same time, until you open the box and Schrodinger's  cat jumps out. Or doesn't.

John


January 03, 2012
On 1/3/2012 10:25 AM, Nick Sabalausky wrote:
> "Walter Bright"<newshound2@digitalmars.com>  wrote in message
> news:jdvgnr$2uer$1@digitalmars.com...
>> On 1/3/2012 12:48 AM, Nick Sabalausky wrote:
>>> "Could an omnipotent being make a
>>> rock that isn't a rock?"
>>
>> I don't know, but I'm sure he could make a product that is both a floor
>> wax and a dessert topping.
>
> I'm having visions of Billy Mays...


Wrong reference! Google "floor wax and dessert topping".
January 04, 2012
This conversation has meandered into one very specific branch, but I just
want to add my 2c to the OP.
I agree, I want D to be a useful systems language too. These are my issues
to that end:

 * __forceinline ... I wasn't aware this didn't exist... and yes, despite
all this discussion, I still depend on this all the time. People are
talking about implementing forceinline by immitating macros using mixins...
crazy? Here's a solid reason I avoid mixins or procedurally generated code
(and the preprocessor in C for that matter, in favour of __forceinline):
YOU CAN DEBUG IT. In an inline function, the code exists in the source
file, just like any other function, you can STEP THE DEBUGGER through it,
and inspect the values easily. This is an underrated requirement. I would
waste hours on many days if I couldn't do this. I would only ever use
string mixins for the most obscure uses, preferring inline functions for
the sake of debugging 99% of the time.

 * vector type ... D has exactly no way to tell the compiler to allocate
128bit vector registers, load/store, and pass then to/from functions. That
is MOST of the register memory on virtually every modern processor, and D
can't address it... wtf?

 * inline assembler needs pseudo registers ... The inline assembler is
pretty crap, immitating C which is out-dated. Registers in assembly code
should barely ever be addressed directly, they should only be addressed by
TYPE, allowing the compiler to allocate available registers (and/or manage
storing the the stack where required) as with any other code. Inline
assembly without pseudo-registers is almost always an un-optimisation, and
this is also the reason why almost all C programmers use hardware opcode
intrinsics instead of inline assembly. There is no way without using
intrinsics in C to allow the compiler to perform optimal register
allocation, and this is still true for D, and in my opinion, just plain
broken.

 * __restrict ... I've said this before, but not being able to hint that
the compiler ignore possible pointer aliasing is a big performance problem,
especially when interacting with C libs.

 * multiple return values (in registers) ... (just because I opened a topic
about it before) This saves memory accesses in common cases where i want to
return (x, y), or (retVal, errorCode) for instance.

Walter made an argument "The same goes for all those language extensions
you mentioned. Those are not part of Standard C. They are vendor
extensions. Does that mean that C is not actually a systems language? No."
This is absurd... are you saying that you expect Iain to add these things
to GDC to that people can use them, and then create incompatible D code
with the 'standard' compiler?
Why would you intentionally fragment the compiler support of language
features rather than just making trivial (but important) features that
people do use part of the language?

This is a great example of why C is shit, and a good example of why I'm interested in D at all...

On 29 December 2011 13:19, Vladimir Panteleev <vladimir@thecybershadow.net>wrote:

> On Thursday, 29 December 2011 at 09:16:23 UTC, Walter Bright wrote:
>
>> Are you a ridiculous hacker? Inline x86 assembly that the compiler actually understands in 32 AND 64 bit code, hex string literals like x"DE ADB EEF" where spacing doesn't matter, the ability to set data alignment cross-platform with type.alignof = 16, load your shellcode verbatim into a string like so: auto str = import("shellcode.txt");
>>
>
> I would like to talk about this for a bit. Personally, I think D's system programming abilities are only half-way there. Note that I am not talking about use cases in high-level application code, but rather low-level, widely-used framework code, where every bit of performance matters (for example: memory copy routines, string builders, garbage collectors).
>
> In-line assembler as part of the language is certainly neat, and in fact coming from Delphi to C++ I was surprised to learn that C++ implementations adopted different syntax for asm blocks. However, compared to some C++ compilers, it has severe limitations and is D's only trick in this alley.
>
> For one thing, there is no way to force the compiler to inline a function (like __forceinline / __attribute((always_inline)) ). This is fine for high-level code (where users are best left with PGO and "the compiler knows best"), but sucks if you need a guarantee that the function must be inlined. The guarantee isn't just about inlining heuristics, but also implementation capabilities. For example, some implementations might not be able to inline functions that use certain language features, and your code's performance could demand that such a short function must be inlined. One example of this is inlining functions containing asm blocks - IIRC DMD does not support this. The compiler should fail the build if it can't inline a function tagged with @forceinline, instead of shrugging it off and failing silently, forcing users to check the disassembly every time.
>
> You may have noticed that GCC has some ridiculously complicated assembler facilities. However, they also open the way to the possibilities of writing optimal code - for example, creating custom calling conventions, or inlining assembler functions without restricting the caller's register allocation with a predetermined calling convention. In contrast, DMD is very conservative when it comes to mixing D and assembler. One time I found that putting an asm block in a function turned what were single instructions into blocks of 6 instructions each.
>
> D's lacking in this area makes it impossible to create language features that are on the level of D's compiler built-ins. For example, I have tested three memcpy implementations recently, but none of them could beat DMD's standard array slice copy (despite that in release mode it compiles to a simple memcpy call). Why? Because the overhead of using a custom memcpy routine negated its performance gains.
>
> This might have been alleviated with the presence of sane macros, but no such luck. String mixins are not the answer: trying to translate macro-heavy C code to D using string mixins is string escape hell, and we're back to the level of shell scripts.
>
> We've discussed this topic on IRC recently. From what I understood, Andrei thinks improvements in this area are not "impactful" enough, which I find worrisome.
>
> Personally, I don't think D qualifies as a true "system programming
> language" in light of the above. It's more of a compiled language with
> pointers and assembler. Before you disagree with any of the above, first
> (for starters) I'd like to invite you to translate Daniel Vik's C memcpy
> implementation to D: http://www.danielvik.com/2010/**
> 02/fast-memcpy-in-c.html<http://www.danielvik.com/2010/02/fast-memcpy-in-c.html>. It doesn't even use inline assembler or compiler intrinsics.
>


January 04, 2012
Manu:

>  * vector type ... D has exactly no way to tell the compiler to allocate
> 128bit vector registers, load/store, and pass then to/from functions. That
> is MOST of the register memory on virtually every modern processor, and D
> can't address it... wtf?

Currently the built-in vector operations of D are not optimized, their syntax and semantics has some small holes that I'd like to see fixed (it's not just a matter of implementation bugs, I also mean design bugs). So I suggest first to improve them a lot, and only later, if necessary, to introduce intrinsics.

Bye,
bearophile
January 04, 2012
On Tuesday, 3 January 2012 at 18:49:35 UTC, Martin Nowak wrote:
> For real performance bottlenecks one should always examine the assembly. For most code inlining hardly ever matters for the runtime of your program and focusing on efficient algorithms is most important.
>
> What really baffles me is that people want control over inlining
> but nobody seems to ever have noticed that x64 switch doesn't switch and x64 vector ops aren't vectorized. Both of which are really important in performance sensitive code.

Quality of implementations' optimizations and a common syntax for code compilation guarantees are orthogonal issues.
January 04, 2012
On 1/4/12 3:39 AM, Manu wrote:
>   * __forceinline ... I wasn't aware this didn't exist... and yes,
> despite all this discussion, I still depend on this all the time. People
> are talking about implementing forceinline by immitating macros using
> mixins.... crazy? Here's a solid reason I avoid mixins or procedurally
> generated code (and the preprocessor in C for that matter, in favour of
> __forceinline): YOU CAN DEBUG IT. In an inline function, the code exists
> in the source file, just like any other function, you can STEP THE
> DEBUGGER through it, and inspect the values easily. This is an
> underrated requirement. I would waste hours on many days if I couldn't
> do this. I would only ever use string mixins for the most obscure uses,
> preferring inline functions for the sake of debugging 99% of the time.

Hmmm, I see that the other way around. D CTFE-generated macros are much easier to debug because you can actually print the code before mixing it in. If it looks like valid code... great.

I think the deal with inline functions is significantly more complex. Inlining is the first step in a long pipeline of optimizations that often make the code virtually unrecognizable and impossible to map back to source in a way that's remotely understandable.


Andrei
January 04, 2012
On Wednesday, 4 January 2012 at 14:28:07 UTC, Andrei Alexandrescu wrote:
> Hmmm, I see that the other way around. D CTFE-generated macros are much easier to debug because you can actually print the code before mixing it in. If it looks like valid code... great.

Paging Don Clugston: would it be feasable to have the compiler remember the source position of every single char/string literal or compile-time-evaluated string expression?

I'm thinking that if the compiler tracks the source of every string/char literal in the source code, all across to any manipulations, debugging CTFE-generated code would be a lot easier - the compiler would emit error messages pointing inside string literals, and debuggers could step inside code in string literals. (The one thing this doesn't allow is allowing debuggers to step through a DSL with no D code in it.)

The naive implementation would store the position of every character, which would blow up the memory usage by about 13 times or so on 32-bit? (For every character, add a struct with 3 fields - char* filename; int line, column). A rope-like structure could cut down on that but possibly drastically complicating the implementation.
January 04, 2012
On 01/04/12 16:31, Artur Skawina wrote:
> Functions attributes seems like it could be an easy, backward compatible addition:
> 
> @attr(attributes...)
> 
> then define some obvious generic attributes like "inline" (which is (always|force)_inline, as it's the only one that makes sense), "noinline", "hot", "cold" etc. This lets you write "@attr(inline) int f(i){}" etc, but doesn't help the vendor specific attr case at all, unfortunately. [2]

User defined attributes.

"@attr regparm=whatever_the_compiler_uses;", conditioned on version().

Would let you do "@attr(regparm) int f(int i){}" in a portable way. Still not sure i like it, but could work. Would have to accept and expand to multiple attrs though...

artur