Brainteasers at SpaceX

Allegedly, Elon Musk, asks people a brain-teaser during the hiring process at SpaceX. I’ve been asked a few myself in my day. Failed them all. “How do you determine if a figure is convex or concave?”, “You have 2 buckets..”, “Three fishermen return from the sea”.

What I now understand is that there are some basic principles involved in these; the earth is a sphere, and – the most difficult one to grasp – the fact that someone doesn’t know, also has some informational value. So, I am not really impressed by someone posing these questions, as if they had come up with them right then and there. In fact, my old boss (John Blem) posed a very similar question to me when I was hired. I suspect he got the question from Mensa (where he is a member), and now, 10 years later, Elon Musk is trying to weed out the posers with a variation of that same old riddle. The man must be a genius.

The real question to ask during an interview is this : “Do you make a new pot of coffee, when you take the last cup?”. If the applicant answers “yes”, the interview ends right there. You do not want to hire an immoral liar. I never make a new pot if I take the last cup. I proudly pour the last cup, and turn the damn coffee machine off. And I stand by my choice; the truth is that 99% of people walk in, see that there is just around 1 cup left (if there is 1.51 cup left, they are OK). And so they decide that the hassle of brewing a new pot is not worth it. Not only that. If the walk out and wait 30 minutes, then some other poor fool must have drunk the last cup of stale coffee, and therefore, new fresh coffee is available. Alas, it’s better to just walk back to your desk and wait.

So, what happens is that the schmuck who takes the last coffee, which by now is thick as molasses, will be punished. He has to make new, fresh coffee for all the assholes who walked in, saw the trap, and backed out. So while he is trying to down a cup of revolting goo, everyone else gets to party with delicious, freshly brewed Joe. Right until there is just one cup left. That gets to sit in the pot, until it too is strong enough to awaken the dead.

This is a tremendous waste of resources. The coffee sits on the burner for hours on end, wasting precious energy like there’s no tomorrow. I could probably charge a few Teslas per day with the amount of energy being wasted on that damn coffee machine.

Yet, in every office I’ve been to, someone took the time to write “If you take the last cup of coffee, make a new pot”, print that shit out, and hang it by the coffee maker. It’s as common as the “wash your own dishes” or “clean up after yourself” printouts. I’d like to know if that ever worked, for anyone, anywhere. I very much doubt that the sign (usually written in Comic Sans – to make it look hand-written, yet I-am-using-a-computer-and-printer-because-I-am-a-professional-and-I-expect-to-be-taken-seriously), will make people go “oh, I wasn’t aware of that rule, but now that I see the words written down, I will change my ways”.

Companies must get one of those machines that brew one cup at a time. For the environment. Both of them.

If you are a job seeker, a company that has one of those old machines, and one or more of those “your mom doesn’t work here” signs, it’s a clear sign that you should run for the hills. Run, and don’t look back.

On Multithreaded Code

Say you want to build a wall. You’ve poured a foundation, and now you need to lay some bricks. If it’s just you working, you can start from one end, and lay bricks one by one, from A to B, one layer at a time.

This is single threaded work.

Since it’s just you, there’s no risk of collision.

Now, you could also lay one brick on one end, then move to the other end, lay one there, move back again, lay one next to the previous. The time spent moving from side to side is context switching. You are doing work, just not work that puts more bricks on the wall. Alas, the total time to completion is lower than if you just did one thing. This is multitasking with one CPU. It can be either preemptive (someone tells you to stop, and do something else, much like a regular job), or cooperative (old windows used this) where you say “I’m done, what now” on regular intervals.

Again, since it is just you, there’s little risk of messing things up (I’ve laid a few bricks… plenty of ways to mess things up alone).

If someone came by, and saw the wall being built (assuming he couldn’t see you working on it), it would seem as if two people were working on the wall. The assumption would then be that the wall would be done 2x faster. That person would be misled.

Now, say you trick your brother in law into helping you out, so now we have 2 CPUs or cores. It doesn’t really matter what you call them, in the old days it was 2 physical chips side by side, today it’s – usually – all inside one chip. So you both start at different ends, work towards the middle, and when you meet, you go back to your end and start a new layer. You could also have your brother in law mix the mortar, hand you bricks etc.

But now you have to coordinate things. You have to keep track of what the hell that brother in law of yours is doing. To do this we have a bunch of tools at our disposal : mutex, semaphore, event. These are control mechanisms that need to be applied carefully.

For example, say tell your brother in law to sit and wait, until you’ve laid a brick, until he can lay his. So you lay one, while he is waiting, then you wait while he lays one, and then back to you.

This may look like multithreading, and in a sense it is, but it is no faster than if it was just you doing the work alone. To the outsider, like before, it’s really hard to tell the difference. Clearly two people are working on the wall, but is it any faster than just one? It depends on how they work. How the mutexes, semaphores and events are applied.

In windows, there’s a bunch of fakery going on behind the scenes. One common problem is that the windows UI can usually only be updated from one thread. If you create a worker thread, and that thread then needs to update a progress bar, then you need to jump through some hoops to get that bar to update.

The hoops usually involve putting your command into a single-threaded queue, and then waiting for the work to be done. So now all of the workers are waiting in line to fill out a sheet, instead of just distributing the sheets to all the workers and have them fill them out in parallel.

But this technique is being used behind the scenes too. If, for example, you are not careful about how you design your COM objects (ancient technology, but useful nonetheless), then your carefully crafted multithreaded code might actually be single-threaded, and just appear to be multithreaded because you called CreateThread somewhere.

Some people tend to think that code that keeps the CPU load at a low percentage is always good. But you have to look at the output too. I had this shit piece of code, that ran at 25% CPU utilization and gave me 200 fps. But I had 4 cores, and I was just not able to go to 100%. Obviously, at 100% I should be able to get at least 600 fps. Sure enough, there was a long line at the office, and every worker was standing in line. Applying the mutexed correctly, allowed me to use all of the CPU if I wanted to.

Same applied to Visual Studio, compilations took forever because we are importing some files. After re-organizing the build sequence, we were able to max out all cores when compiling, significantly reducing compile time.

Multithreaded can be fast, but you have to do it right, and check your assumptions (this is almost always true).