_- Faster C++

Birth and death of an Heisenbug

Posted on

I came across a weird C++ line of code that I wanted to share, although it does not deal with fast C++. For the sake of simplicity, I dropped all the fancy data structures and replaced them with plain old data types. It goes like this :

int a, b; a, b = 5, 6; cout << a << endl; // a random value is printed!

The code was written by a young developer who is quite knowledgeable about C++17 and Python. And in fact Python allows that sort of comma-separated assignment. In C++, it compiles fine with our release flags, where there is no warning enabled. In our debug compilation setup, specifically with the -Wall flag, it produces the following warning at the first line where the variable 'a' is read:

warning: 'a' is used uninitialized in this function [-Wuninitialized]

I tested this with GCC 4.8.1. The thing is that our debug flags are so extensive that there are literally tons of warnings. So much that people simply don't pay attention to the build outputs anymore! As a side note, those warnings are not necessarily from our codebase. But rather from the third party libraries' headers we compile against. That important warning about the uninitialized variable therefore remained unnoticed, lost in the middle of the massive compiler outputs. The uninitialized variable manifested as an Heisenbug, a random crash. The type of problem I am the most worried about. The ones that highlight poor code quality. The developer could not find the origin of the crashes, and asked me for help. But the crashes occurred at random places, and quite far from the guilty line of code! Finding the source of the problem was such a pain. I may write a post in the future to explain my precise walkthrough. The key tool that helped me is Valgrind. Specifically the Memcheck tool, with the '--track-origins=yes' option, ran on a debug build of the program. It yielded the following information:

"Conditional jump or move depends on uninitialized value(s)"

Together with the full stack trace, including all files and lines of code involved. This led me to the culprit! My advice would be addressed to developers navigating across C++ and Python. While C++ has gotten alot easier to write in an ongoing effort right from C++11, it does not share the exact same principles than Python. Another advice would be to restrict the debug compilation flags to those which really influence code quality. Reducing the number of flags will accelerate compilation duration, and make important warnings stand out. Work on your building suite to let the compiler help you out as much as possible!

Benchmarking. The smart way.

Posted on

I really enjoyed watching this talk about code performance on Youtube (Full video at the end). I thought it would be worth to share its content here. But the talk is so informative that a single blog post would never be enough to cover its entirety. So in this post I will solely focus on benchmarking. Precisely on how to evaluate code performance in a smarter way than what is usually done in the industry. The problem of comparing performance plots on various use cases is so frequent, yet so mishandled. It is surprising because interpreting timings, thus concluding on the best variation of a program, has a mathematical solution known since 1908! Waaaay before C++ was even designed! The solution is the Student test. It itself has a very interesting history, and I might write a future post about it! Simply put, the Student test provides a formal criterion to tell whether two sets of random samples belong to the same normal distribution. How to apply this test to benchmarking? Just run two variations of a program on a benchmark suite. This will give you two series of timings, most probably with different means and standard deviations. But think about it: Even if there was no variation at all in the program between the two runs, you would observe different means and standard deviations! This is due to the execution noise, which is why one does multiple runs of the same benchmark in the first place! So those differences must be marked as irrelevant, and discarded. This is why there is a need for a precise benchmarking criterion. You name it: the Student test. Given two sets of timings on two variations of a program, the Student test is able to tell whether those differences can be attributed to the execution noise, or one variation is superior to the other. Here is the full talk:



Copyright © 2022-2026
Créé par Janahan Nallanathan