Simplifying code

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Simplifying code

Post by mvanthoor »

Joost Buijs wrote: Tue Oct 06, 2020 5:15 pm In the past when compilers were not that smart a different programming style was needed to get good performance, basically you had to optimize the whole code flow by hand, fortunately this no longer necessary.
Indeed; I sometimes have to remind myself that extra variables don't mean that the program uses extra memory or extra cpu-cycles. The pawns-function above is one of my more extreme examples; it's basically a massive list of variables/definitions, one building on top of the previous, to calculate an end result. Then at the end of the function, another function is called. The let-statements even make it possible to omit an explicit if-statement, and match-statement.

There's a great video on Youtube with regard to optimization by LLVM. (It's in a video about Rust, but it would be the same for Clang.) There, the speaker shows a function with quite a lot of variables, statements, and even branches, and then he starts to elide (omit) variables, by packing the stuff from the variable directly into the place where the variable is used. (Just like I did with the square-attacked function above.) After that, he continues with the branches and other statements. Eventually he comes to this conclusion:

Original:

Code: Select all

fn do_some_stuff (x : u8) -> u8 {
	let mut result = 0

	//
	// lots of code here to calculate result
	///
	
	return result;
}
After compilation:

Code: Select all

fn do_some_stuff( x: u8 ) -> u8 {
	return x + 10;
}
He even showed that the first and second function actually compile down to the same (few) lines of code.

After a saw that video, I don't really think about using "extra" variables or higher-level language constructs. The compiler will remove all of them. The only thing to watch out for, is allocations. (Don't use a vector if an array will do; that sort of thing.)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
JohnWoe
Posts: 491
Joined: Sat Mar 02, 2013 11:31 pm

Re: Simplifying code

Post by JohnWoe »

I usually parenthesis everything. I have 0 trust in compilers getting operator precedence correct.

Over commenting is a much bigger problem than no comments. As you have to maintain comments on top of the code.
JohnWoe
Posts: 491
Joined: Sat Mar 02, 2013 11:31 pm

Re: Simplifying code

Post by JohnWoe »

mvanthoor wrote: Tue Oct 06, 2020 6:09 pm
Joost Buijs wrote: Tue Oct 06, 2020 5:15 pm In the past when compilers were not that smart a different programming style was needed to get good performance, basically you had to optimize the whole code flow by hand, fortunately this no longer necessary.
Indeed; I sometimes have to remind myself that extra variables don't mean that the program uses extra memory or extra cpu-cycles. The pawns-function above is one of my more extreme examples; it's basically a massive list of variables/definitions, one building on top of the previous, to calculate an end result. Then at the end of the function, another function is called. The let-statements even make it possible to omit an explicit if-statement, and match-statement.

There's a great video on Youtube with regard to optimization by LLVM. (It's in a video about Rust, but it would be the same for Clang.) There, the speaker shows a function with quite a lot of variables, statements, and even branches, and then he starts to elide (omit) variables, by packing the stuff from the variable directly into the place where the variable is used. (Just like I did with the square-attacked function above.) After that, he continues with the branches and other statements. Eventually he comes to this conclusion:

Original:

Code: Select all

fn do_some_stuff (x : u8) -> u8 {
	let mut result = 0

	//
	// lots of code here to calculate result
	///
	
	return result;
}
After compilation:

Code: Select all

fn do_some_stuff( x: u8 ) -> u8 {
	return x + 10;
}
He even showed that the first and second function actually compile down to the same (few) lines of code.

After a saw that video, I don't really think about using "extra" variables or higher-level language constructs. The compiler will remove all of them. The only thing to watch out for, is allocations. (Don't use a vector if an array will do; that sort of thing.)
Clang can even optimize a slow "for loop ... " BitCount to 1 assembly call. Clang has some algorithms to recognize algorithms.

I forgot to mention that a well written C program is also a C++ program. As C++ is a multi-paradigm language.

Python on the other the weakest link is the packaging system like in Rust. pip. Always some modules missing/broken and need lots of debugging.
I rather take a 200 MB static package that just works. Drink tea while it downloads.

Than this modern dynamic module system stupidity that works 25% of the time.
Henk
Posts: 7218
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

JohnWoe wrote: Thu Oct 08, 2020 10:05 pm
mvanthoor wrote: Tue Oct 06, 2020 6:09 pm
Joost Buijs wrote: Tue Oct 06, 2020 5:15 pm In the past when compilers were not that smart a different programming style was needed to get good performance, basically you had to optimize the whole code flow by hand, fortunately this no longer necessary.
Indeed; I sometimes have to remind myself that extra variables don't mean that the program uses extra memory or extra cpu-cycles. The pawns-function above is one of my more extreme examples; it's basically a massive list of variables/definitions, one building on top of the previous, to calculate an end result. Then at the end of the function, another function is called. The let-statements even make it possible to omit an explicit if-statement, and match-statement.

There's a great video on Youtube with regard to optimization by LLVM. (It's in a video about Rust, but it would be the same for Clang.) There, the speaker shows a function with quite a lot of variables, statements, and even branches, and then he starts to elide (omit) variables, by packing the stuff from the variable directly into the place where the variable is used. (Just like I did with the square-attacked function above.) After that, he continues with the branches and other statements. Eventually he comes to this conclusion:

Original:

Code: Select all

fn do_some_stuff (x : u8) -> u8 {
	let mut result = 0

	//
	// lots of code here to calculate result
	///
	
	return result;
}
After compilation:

Code: Select all

fn do_some_stuff( x: u8 ) -> u8 {
	return x + 10;
}
He even showed that the first and second function actually compile down to the same (few) lines of code.

After a saw that video, I don't really think about using "extra" variables or higher-level language constructs. The compiler will remove all of them. The only thing to watch out for, is allocations. (Don't use a vector if an array will do; that sort of thing.)
Clang can even optimize a slow "for loop ... " BitCount to 1 assembly call. Clang has some algorithms to recognize algorithms.

I forgot to mention that a well written C program is also a C++ program. As C++ is a multi-paradigm language.

Python on the other the weakest link is the packaging system like in Rust. pip. Always some modules missing/broken and need lots of debugging.
I rather take a 200 MB static package that just works. Drink tea while it downloads.

Than this modern dynamic module system stupidity that works 25% of the time.
No need for C++. Object orientation is already refuted. OO only worked for Simula.
Better use composition, modules and records. Immutability makes refactoring easier. Also reduce coupling between modules as much as possible.
All nothing new. Already innvented in 70's. Distributed programming only makes it complex.
JohnWoe
Posts: 491
Joined: Sat Mar 02, 2013 11:31 pm

Re: Simplifying code

Post by JohnWoe »

Henk wrote: Thu Oct 08, 2020 11:18 pm
JohnWoe wrote: Thu Oct 08, 2020 10:05 pm
mvanthoor wrote: Tue Oct 06, 2020 6:09 pm
Joost Buijs wrote: Tue Oct 06, 2020 5:15 pm In the past when compilers were not that smart a different programming style was needed to get good performance, basically you had to optimize the whole code flow by hand, fortunately this no longer necessary.
Indeed; I sometimes have to remind myself that extra variables don't mean that the program uses extra memory or extra cpu-cycles. The pawns-function above is one of my more extreme examples; it's basically a massive list of variables/definitions, one building on top of the previous, to calculate an end result. Then at the end of the function, another function is called. The let-statements even make it possible to omit an explicit if-statement, and match-statement.

There's a great video on Youtube with regard to optimization by LLVM. (It's in a video about Rust, but it would be the same for Clang.) There, the speaker shows a function with quite a lot of variables, statements, and even branches, and then he starts to elide (omit) variables, by packing the stuff from the variable directly into the place where the variable is used. (Just like I did with the square-attacked function above.) After that, he continues with the branches and other statements. Eventually he comes to this conclusion:

Original:

Code: Select all

fn do_some_stuff (x : u8) -> u8 {
	let mut result = 0

	//
	// lots of code here to calculate result
	///
	
	return result;
}
After compilation:

Code: Select all

fn do_some_stuff( x: u8 ) -> u8 {
	return x + 10;
}
He even showed that the first and second function actually compile down to the same (few) lines of code.

After a saw that video, I don't really think about using "extra" variables or higher-level language constructs. The compiler will remove all of them. The only thing to watch out for, is allocations. (Don't use a vector if an array will do; that sort of thing.)
Clang can even optimize a slow "for loop ... " BitCount to 1 assembly call. Clang has some algorithms to recognize algorithms.

I forgot to mention that a well written C program is also a C++ program. As C++ is a multi-paradigm language.

Python on the other the weakest link is the packaging system like in Rust. pip. Always some modules missing/broken and need lots of debugging.
I rather take a 200 MB static package that just works. Drink tea while it downloads.

Than this modern dynamic module system stupidity that works 25% of the time.
No need for C++. Object orientation is already refuted. OO only worked for Simula.
Better use composition, modules and records. Immutability makes refactoring easier. Also reduce coupling between modules as much as possible.
All nothing new. Already innvented in 70's. Distributed programming only makes it complex.
I see C++ as improved C. I rather use std::vector than write my own buggy container with malloc/free.
So C++ offers extra tools I can use. Why I shouldn't use them?
C is like assembly with syntax sugar. It's fast tho. As it maps to assembly. My dumb engine plays 2300+ Elo because assembly speed.

I usually use whatever technique offers the least amount of code.

I just installed Rust 300 MB! I don't like all this bloat.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Simplifying code

Post by mvanthoor »

JohnWoe wrote: Fri Oct 09, 2020 1:07 pm I see C++ as improved C. I rather use std::vector than write my own buggy container with malloc/free.
So C++ offers extra tools I can use. Why I shouldn't use them?
C is like assembly with syntax sugar. It's fast tho. As it maps to assembly. My dumb engine plays 2300+ Elo because assembly speed.

I usually use whatever technique offers the least amount of code.

I just installed Rust 300 MB! I don't like all this bloat.
LOL. I have never written "proper C++". I did the same things as you; write C, but use stuff from the C++ stdlib (and Boost). The only thing with regard to object oriented programming that I did in C++ was to stick some data and functions that belong together into a class.

Fortunately, Rust is a language that fits me to a T in that regard. It doesn't have objects (or inheritance), but it does have structs with member functions.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Henk
Posts: 7218
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

mvanthoor wrote: Fri Oct 09, 2020 1:36 pm
JohnWoe wrote: Fri Oct 09, 2020 1:07 pm I see C++ as improved C. I rather use std::vector than write my own buggy container with malloc/free.
So C++ offers extra tools I can use. Why I shouldn't use them?
C is like assembly with syntax sugar. It's fast tho. As it maps to assembly. My dumb engine plays 2300+ Elo because assembly speed.

I usually use whatever technique offers the least amount of code.

I just installed Rust 300 MB! I don't like all this bloat.
LOL. I have never written "proper C++". I did the same things as you; write C, but use stuff from the C++ stdlib (and Boost). The only thing with regard to object oriented programming that I did in C++ was to stick some data and functions that belong together into a class.

Fortunately, Rust is a language that fits me to a T in that regard. It doesn't have objects (or inheritance), but it does have structs with member functions.
I have programmed at least 6 years in C++. And after that C#. Only difference should be that you put first argument in a class. Instead of passing a record. By the way C++ better than C because of better type checking in C++. I am using associationLists/immutableDictionaries now instead of records. Like in LISP.

Might make it even more slow.

1) no goto
2) Modular
3) No side effects if possible
Henk
Posts: 7218
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

Can't even use iterators in critical code for that means allocating memory.

So enjoy ugly code.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Simplifying code

Post by Sven »

Henk wrote: Fri Oct 16, 2020 10:08 am Can't even use iterators in critical code for that means allocating memory.

So enjoy ugly code.
Iterators, as we know them from C++ STL for instance, have an intrinsic ugliness 😉

So you might want to write your own, nice, efficient, non-allocating iterators ...
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7218
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

I have also this Neural Network crap in my source code. Don't know what to do with it.
Who wants a black box. Nobody.