Help improving this code ?!

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Ras
Posts: 2496
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Help improving this code ?!

Post by Ras »

mar wrote:I wonder why people still believe in the myth that C is faster than C++
Because you need to know a lot more about C++ than about C for an equally fast solution - C++ is much more complex and thus offers much more opportunities to do it wrong. Wrong like in "it works, just slower than possible".
mar
Posts: 2567
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Help improving this code ?!

Post by mar »

Ras wrote:Because you need to know a lot more about C++ than about C for an equally fast solution - C++ is much more complex and thus offers much more opportunities to do it wrong. Wrong like in "it works, just slower than possible".
Sorry, that seems like a logical fallacy to me - complexity of C++ has nothing to do with performance.
How is C++ for loop on integer or stack array access slower in C++ than C?
Can you give an example to your claim?

C++ is more complicated but on the other hand allows you to do complicated things much easier than in C,
do you believe that macro magic is easier/more elegant than C++ templates?
Or do you think than function tables in C are more elegant to use than methods in C++?
Do you prefer this_function_takes_two_floats in C over overloads?

Everything that can be done in C++ can be done in C, but for a complicated project I'd choose C++ over C anytime.
Also I'd choose C over assembly anytime as well.

"More opportunities to do it wrong" - right, but nobody said C++ is for kids,
C++ is for people who know what they're doing, but so is C.
People who don't understand pointers should stay away from C for example,
there are always many ways to do things wrong in either language because both allow you to write low level code.
Ras
Posts: 2496
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Help improving this code ?!

Post by Ras »

mar wrote:Sorry, that seems like a logical fallacy to me - complexity of C++ has nothing to do with performance.
Not if done right, of course. But more language complexity, more features means more ways to use them wrong. That's simple logic.
Can you give an example to your claim?
Just new an object in a tight loop with tons of mallocs. Something you can't do wrong with C because C has no new.

Obviously, there is no need to do so (in fact, it is stupid), but in order to understand that, you have to know how exactly new works. You can't use that language with blackbox programming, as you normally would with abstractions.

And it doesn't stop at the language, you have to know STL and Boost just as well, which is a lot of powerful stuff in its own. If used right, things are no slower than in C. If, and that's no small if - that's where Torvalds' rants come from.
C++ is more complicated but on the other hand allows you to do complicated things much easier than in C
In fact, for a complex project, I wouldn't select C. Mainly because the ressource management is fully manual, which slows down time to market. I'd do C for the speed critical 2% of the project and do the rest in some other language, e.g. Python or so.
"More opportunities to do it wrong" - right, but nobody said C++ is for kids, C++ is for people who know what they're doing
Exactly. Given the real world code I've seen in my life, no matter what language, a considerable part of real life programmers work by a very simplified model of the language and not by what the standard actually says.

Since the majority of projects isn't done by world-class professionals simply because the customers won't pay world-class professional prices, that is what got C++ the image of being slower. In the hands of average programmers, this may well be the case. In the hands of pros, it isn't.

That's similar for Java, btw - it isn't the language, it is a lot of programmers.
mar
Posts: 2567
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Help improving this code ?!

Post by mar »

Ras wrote:If, and that's no small if - that's where Torvalds' rants come from.
I need to find his rants about C++, out of curiosity.

I personally think that for something as low level as OS kernel, C++ is not a good choice - C seems like an excellent choice here.
It's trivial to interface with C code from various languages and you can always wrap the functionality in a higher level concept.
Ras
Posts: 2496
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Help improving this code ?!

Post by Ras »

mar wrote:I need to find his rants about C++, out of curiosity.
This one here: http://lwn.net/Articles/249460/

I don't think that it actually holds water if C++ pros are aboard, but he might have a point with not-so-pro-blackbox-programmers. That one was about Git, not about the kernel, so it actually was application layer where C++ isn't out of place. And of course that was 8 years since.

You see, even with C, I have seen real world stuff like IO register mapping with bitfields (WTF). Imagine giving C++ to such programmers, and you're in for desaster.
Ras
Posts: 2496
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Help improving this code ?!

Post by Ras »

mar wrote:Can you give an example to your claim?
Oh, and I totally forgot the obvious. Consider the following task:

- choose an open source engine from the CCRL, listed at no less than ELO 2100
- port that to a Cortex M4 with 1MB ROM, 192kB RAM (the RAM even being split into two disjunct address ranges) and no MMU (memory fragmentation raising its head)

To be fair, any engine that uses bitboards is out of question, no matter whether C or C++ (bitboards are too heavy anyway).

C++ on microcontrollers is possible, but in practice amounts only to "C with classes", or "C+". But since there are no C++ engines that limit themselves to C+ (why would they?!), this is just theory.

Every seemingly innocent line of C++ may well have a lot of stuff going on behind the scenes (that's the point of abstraction), and all the compiler magic, STL or Boost suddenly turn against you. That's extra fun if the engine in question was written by someone else.

It was quite some work even in C. Your take on such a project with C++?
mar
Posts: 2567
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Help improving this code ?!

Post by mar »

Ras wrote: Oh, and I totally forgot the obvious. Consider the following task:

- choose an open source engine from the CCRL, listed at no less than ELO 2100
- port that to a Cortex M4 with 1MB ROM, 192kB RAM (the RAM even being split into two disjunct address ranges) and no MMU (memory fragmentation raising its head)

To be fair, any engine that uses bitboards is out of question, no matter whether C or C++ (bitboards are too heavy anyway).

C++ on microcontrollers is possible, but in practice amounts only to "C with classes", or "C+". But since there are no C++ engines that limit themselves to C+ (why would they?!), this is just theory.

Every seemingly innocent line of C++ may well have a lot of stuff going on behind the scenes (that's the point of abstraction), and all the compiler magic, STL or Boost suddenly turn against you. That's extra fun if the engine in question was written by someone else.

It was quite some work even in C. Your take on such a project with C++?
I see. I certainly think it should be doable, depends on how much space would libstdc++ take. See for example Steven's Myopic: https://chessprogramming.wikispaces.com/Myopic

In the end, it boils down to machine code anyway.

As for STL/Boost, I'm not a fan of either. In fact, you don't have to use them because they're themselves just programs written in C++,
which shows the power of the language itself.

When doing global optimizations, the compiler/linker also merges binary-identical functions. Naturally you'd want to reduce code size.

So the only thing that bothers me a bit is compilation times. C easily outperforms C++ here (depending on what you do of course).
(for tiny projects like chess engines this is not a big deal)

I'm not a fan of precompiled headers but they can help as well.

But you can use so called unity builds - where everything is compiled as a single source file, including every cpp file that's needed.
I think Bob does this in Crafty and some people laughed at him because of that, but in fact this is very common for large projects.
A colleague who worked on Mafia II told me that they used unity build and it massively improved compile times.

The point is that each include is only parsed once (otherwise it's parsed many times for each cpp file you compile)

Of course you can do the same for C projects, but in general you have to be careful to avoid name clashes (per-file local statics for example) - this of course holds for both C and C++.

Other than that we can also hope for C++ modules making it into the standard (unless they made it already).
Ras
Posts: 2496
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Help improving this code ?!

Post by Ras »

mar wrote:I see. I certainly think it should be doable, depends on how much space would libstdc++ take.
Not only. One of the issues is that with 200k without MMU, memory fragmentation is always close, so no dynamic memory management must be used at all. That's pretty much normal for embedded.

Now of course, C++ doesn't enforce dynamic allocation, to be sure. But (and that is a big "but") when taking an existing PC engine, what are the chances that the coder has been alloc paranoid without any valid reason (on the PC)?

And how much work will it be to convert all of that to either static or stack usage? Not to mention that "of course", a stack usage analysis is required for recursive algorithms when running on a microcontroller. 28k of stack isn't that much.

You see, I even kicked out libc (C project) for the target platform. There isn't even an operating system to rely on.
See for example Steven's Myopic:
Fails the criteria (being listed in CCRL with at least ELO 2100). That's an example where a chess engine has been developed in (more or less) C+ from the beginning, with microcontrollers in mind.

The idea was to take a reasonably strong engine without starting from scratch. The funny thing is that code reuse has always been linked to OOP in general. Only that I found in this case plain C had much better reuse.

While you can go that low-level with C+ too, I just doubt that an existing C++ 2100+ PC engine can be ported to that environment. With C, it is definitely possible.

In theory, the footprint of C++ doesn't have to be more than with C. In reality, this only happens when limiting oneself to features that are more or less alao available in C, so the "++" factor is also "++" in footprint when used.
In the end, it boils down to machine code anyway.
The point I wanted to make is that abstraction is a double-edged sword. When it works, it's nice and productive. It becomes endless pain when it doesn't.
In fact, you don't have to use them
Of course. But what are the chances that you find a PC engine which limits itself to pure C++? Why would they reinvent the wheel?
Naturally you'd want to reduce code size.
Code size isn't even the main issue, 1MB is quite much. 249k used, half of it for opening book and KPK endgame table.
So the only thing that bothers me a bit is compilation times.
For such smallish projects like chess engines, I agree this isn't an issue. I don't even use "make" and instead compile the whole thing via batch file or shell script, takes 17 seconds, including the CRC32 for the binary hex file.
mar
Posts: 2567
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Help improving this code ?!

Post by mar »

Ras wrote:Of course. But what are the chances that you find a PC engine which limits itself to pure C++? Why would they reinvent the wheel?
Maybe not for a chess engine.
But there's a plenty of reasons to "reinvent a wheel". I hate this phrase, because basically everyone programming is "reinventing a wheel" so why even bother?

A couple of examples:
std streams are utter crap, dynamic_cast as well. std::vector takes 32 bytes in 64-bit mode, why not "reinvent" something that only takes 16 (assuming you don't need more than 2G elements), while still offering custom allocators.
unordered_set implementation in libstdc++ doesn't perform well (=it's crap), I prefer intrusive ref counting and so on. YMMV, but I like the freedom the language gives me.
stl implementations can (do actually) vary among compilers, while a custom "wheel" always works as expected.

That being said I would prefer this custom wheel that fits my needs anytime,
it only does what I really need (reduces bloat) and it works the way I want.
pijl
Posts: 115
Joined: Mon Sep 17, 2012 8:59 pm

Re: Help improving this code ?!

Post by pijl »

Ras wrote:
mar wrote:I wonder why people still believe in the myth that C is faster than C++
Because you need to know a lot more about C++ than about C for an equally fast solution - C++ is much more complex and thus offers much more opportunities to do it wrong. Wrong like in "it works, just slower than possible".
This is utter nonsense. Most C programs can be compiled directly with a C++ compiler. Those that can't are using dodgy tricks that you should avoid anyway, but if you want to use them anyway you still can (by making some explicit typecasts).

In the Baron I'm using C++ throughout the engine, where it used to be plain C. The main reason is that I started to use classes instead of struct to be able to asserts to the data members in the access methods instead of scattered everywhere in my code.

I started doing this when working on my Havannah program. It had quite complex data structures to be able to efficiently detect rings and chains. I wrote this initially in C. A nightmare to debug. When I decided to move to C++ it was for this reason: To be able to test my data structures for consistency upon every modification I made to them when debugging the program. This worked very well and was prepared to take a performance hit if that would be the consequence of it. But to my surprise the resulting program was even faster. Something I could only explain by the fact that in C++ classes (and by appropriate use of const modifiers) the compiler had more information to optimize the program with and was successful in doing so. This did not yield something in all cases, but did not make it slower in any of them either.

Having more options to do things in a language means you can choose the one most suitable for you. It doesn't mean you have to start using STL, complex class inheritance or other things you don't need.