On programming

<< < (2/11) > >>

Mefiante (May 31, 2011, 15:39:54 PM):
.Net usually “compiles” to MSIL, not native (x86) code. MSIL is a bit like Java’s byte code in that it requires a platform-specific runtime environment.

'Luthon64
BoogieMonster (May 31, 2011, 16:44:58 PM):
Permit me to derail a little more. (Maybe spawning a new thread is in order… ;D )

;D

Quote
You claim that IO ops are costly. This is true if your IO source/target is non-volatile storage.

Maybe not on a Cray but it's common to have PC's or servers (and those sometimes stick around for a while) where the memory is 1/2 the clock speed of the CPU or less. Things are improving though.

Quote
But many specialised scientific/engineering problems are amenable to being memory managed in such a way that misalignment wait-states, fragmented memory blocks and virtual memory access penalties are minimised or even eliminated altogether. This requires a detailed familiarity with the hardware architecture and the innards of the OS you’re coding for.

Yeah I think this is where the crux of this discussion comes. Hand rolling assembly has application in specialised fields like this where you know your hardware and OS intimately, I completely agree. But for the "general purpouse guy" like me, even for server software, it's usually about optimising DB access, network access, and the like. Not so much about cycles. So we're just coming from 2 different applications. And my point is a bit that, the compiler writers cater to the application guys more, in my opinion.

Quote
While on the subject of “good C++,” are you aware of how awfully expensive the object destructors and, especially, the constructors are? I assume you make regular use of structured exception handling too. Do you know what exception handling costs?

Yes, and it depends. Constructor writers have to be prudent to use initialisation lists, and avoid assignments to mitigate costs. Usually you want your constructor body to be empty, the compiler can do initialisation lists quite efficiently. If constructors are very slow it's probably because there's got more stuff in the object than is needed, leading to objects being constructed needlessly, hinting maybe at a bad design decision. One could also be writing code that is creating too many temporaries, resulting in unwanted construction/destruction overhead... the liberal use of references can save one a good whack of unneeded temporaries.

Since we're now completely off topic:
Quote
Constructor(std::string a)
{
this->a = a;
}

is way worse than writing:

Quote
Constructor(const std::string& a): a(a)
{ }

And a lot of people don't realise that. Yes I haven't completely removed constructors, but you can remove a lot of them with some diligence. At the end of the day the memory would need to be initialized one way or the other, but it's nice to only do it once. (Unless, as I suspect, in your domain you may have wanted to forego it because you know exactly how it's going to be used, and program very carefully). I (actually we) don't use exceptions regularly. We try to constrain those to TRULY "exceptional" cases (Network errors, OS errors...), for general error handling we avoid them, not only for performance, but certain guarantees are impossible to enforce when you allow exceptions.

BUT that is only what the language gives you. It's possible to write a block memory allocator in pure C++ that performs. It's a tricky task to make the compiler do a lot of the heavy lifting, usually involving "bending" the template language.... but I know a person who did this, don't know much about it though.

Oh and on destruction... this is a trade-off. It sounds like you were working with large areas of contiguous memory that could be nicely block-allocated and managed. But in our problem space what is needed is often unpredictable up front. So you have the option: Destruction, or Garbage collection. I prefer destruction because the de-allocation, or disconnect/cleanup code is going to happen anyway, albeit in a cascading fashion. I'd suspect though, that clean nested destructors devoid of unnecessary(not de-allocation) code could be optimised into a single de-allocate by the compiler. I'd have to read up though.

Quote
...Thus, you need to understand the nature of the problem you’re dealing with as well as the platform you’re going to solve it on.

Bingo, I do understand that in certain science disciplines this is entirely necessary. The shift seems to be going in the direction of offloading repetitive tasks like those onto GPU's, which have their own languages and compilers to optimise their efficiency, and are very efficient at massively parallel processing (I hear).

Quote
I’m not saying that you have to write your entire program in highly optimised code. That would be a waste of much effort. However, where the nature of the problem warrants it, you should write the critical parts in carefully optimised code such as Assembler, and then link the assembled object code into the rest of your program using the high-level-language development environment (some of which allow you to make use of inline Assembler code).

For us cross-platform guys it's not usually an option. The case would have to be really extreme for us to consider having specialised asm code for every architecture. And hence this discussion.... horses for courses. But lemme let you in on a little secret: We DO have an atomic integer implemented in asm for every platform we support, it's a shitload more efficient than locking when it's applicable.
BoogieMonster (May 31, 2011, 16:51:11 PM):
.Net usually “compiles” to MSIL, not native (x86) code. MSIL is a bit like Java’s byte code in that it requires a platform-specific runtime environment.

'Luthon64

To my shock I realised, upon touching a windows compiler again the other day, that by default the new versions of MSVC++ compile to byte-code too! No kidding, I fire up the exe and .net launches in the background? what the hell? Luckily I found a way to turn it back to "good old fashioned" binary building. :/
Mefiante (May 31, 2011, 18:12:02 PM):
Maybe not on a Cray but it's common to have PC's or servers (and those sometimes stick around for a while) where the memory is 1/2 the clock speed of the CPU or less.
But that’s just my point: If you properly understand the CPU’s prefetching & trace caching, pipelining and memory caching, and you schedule your instruction streams properly over the entire stretch of critical code, these clock penalties simply won’t apply at all because there’s nothing the CPU has to wait for. Everything’s in the queue/cache already by the time it is needed. Put another way, upgrading to faster RAM won’t do much for the performance of such optimised code. (Of course, in practice it’s difficult to achieve 100% CPU efficiency, but 95%+ is doable.)

The codes I’m referring to are normally highly specialised and are used by a small fraternity only. The programmer knows what the target hardware is (or s/he is in a position specify it). It would be a different matter if wide platform coverage was required but this isn’t usually so. Also, code optimisations that work well for one generation of hardware are often well optimised for subsequent generations. The standout exception to this was Intel’s early P4 CPU. It ran P-III optimal code slower than the P-III, even at 50% higher clock speed. At around that time, AMD bit a sizeable chunk out of Intel’s pie.

Another point to note is that there is a certain class of problems that cannot be efficiently parallelised. That is, throwing a problem of this kind at a computing cluster won’t give appreciably faster results than running it on an autonomous single-CPU box of the same hardware configuration. So once again the message is that you need to understand the nature of the problem you’re dealing with.

Hand rolling assembly has application in specialised fields like this where you know your hardware and OS intimately, I completely agree. But for the "general purpouse guy" like me, even for server software, it's usually about optimising DB access, network access, and the like. Not so much about cycles. So we're just coming from 2 different applications. And my point is a bit that, the compiler writers cater to the application guys more, in my opinion.
Agreed in all respects, except to reiterate that even for general-purpose programming, it’s still a real benefit if the programmer understands what the high-level code’s going to be doing on the CPU.

One of the most horrendous bits of OOP I’ve ever seen was actually done by a computer science graduate. In one function that was typically called many millions of times, there was a “while” loop. Within the scope of this “while” construct, an object of a certain class was instantiated for the sake of one method that was needed, and then dutifully destroyed again. The object in question wasn’t used anywhere else in the code, either directly or via descendant classes. When you encounter something so obviously inept, you have to wonder how on earth the offender managed to graduate.

'Luthon64
rwenzori (May 31, 2011, 18:17:14 PM):
so, ummm.... How many programmers are on this forum??? :/

Anyone for COBOL? ;)

Like Mandarb, I'm not at the level of assembler ( way too lazy ) and I never got my head around C or C++, but I have made my living programming in BASIC ( post-COBOL LOL! ), contract programming and selling shareware, way back when. Now just hobby projects for me and friends.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Skeptic Forum Board Index

Non-mobile version of page