Live data from Hacker News

Hell is a multi-threaded C++ program (2006)

codemines.blogspot.com

101–110 of 129 posts

Re: Hell is a multi-threaded C++ program (2006)

#101

Earlier quoted context omitted.

> you have to declare the synchronization semantics for every global when you do. (That is, they have to be read only, or thread local, or atomic, or protected by a lock.) That doesn't sound like it helps you determine which one of those is appropriate. So it seems rather like a system that will lead to unexpected bottlenecks when you parallelize. (Somebody deep inside the stack arbitrarily decided locking was the mo…

> a system that will lead to unexpected bottlenecks when you parallelize This is a funny comment. You are implying that performance is of higher value than correctness. Speed without correctness is dangerous, and leads to significant bugs, especially when you're talking about concurrent modification of state across threads. I'll take correct and need to improve performance over incorrect and fast where the cost of tr…

> This is a funny comment. You are implying that performance is of higher value than correctness.

Of course it is. Tony Hoare noticed it as far back as 1993: given a safe program and a fast program, people would always choose the fast one. Correctness in a mathematical sense does not always map to correctness in the business sense; it's sometimes much more cost-effective to reboot a computer every day and not free any memory than try to be memory-correct which will cost at least a few thousand dollars more in employee time.

Re: Hell is a multi-threaded C++ program (2006)

#102
post #69

I've been writing massively threaded C++ code since the 1990's, so I can comment with some serious experience here. My code used to run on 256CPU SGI's and had high cpu utilization across all of them. When designing C++ code for threading, you have to keep a few things in mind, but it's not particularly harder than on other languages with thread support. You generally want to create re-entrant functions which pass al…

Obviously it is possible to write threaded C++ programs. And there are experienced people like you who can do it well, with enough discipline, good design, and so on. But I think the point of the article is that for most programmers it is very easy to make mistakes and shoot themselves in the foot with threads and shared memory. It could be even something like using a 3rd party library where it's initialization conte…

> So everyone agrees that's sane and normal and say putting their latest production release on a Windows 3.1 would not be a good idea.

And yet unikernels are here and used.

Re: Hell is a multi-threaded C++ program (2006)

#103
post #10
post #2

I've found message passing and thinking in transactions are pretty good architectural patterns for maintaining ones sanity. Message queues with spinlocks for performance critical code (mutexes are slow). The biggest sin generally is to disregard the overhead caused by thread management and thinking more threads makes the sofrware run faster. I've seen people try to parallellize a sequential program by just spawning m…

> spinlocks for performance critical code (mutexes are slow). Gah, no. Userspace spinlocks are the deepest of voodoo and something to be used only by people who know exactly what they are doing and would have no difficulty writing "traditional" threaded code in a C/C++ environment. Among other problems: what happens when the thread holding the spinlock gets preempted and something else runs on the core? How can you p…

> Gah, no. Userspace spinlocks are the deepest of voodoo and something to be used only by people who know exactly what they are doing and would have no difficulty writing "traditional" threaded code in a C/C++ environment.

If you ever used pthread_mutex with glibc then you use spinlocks without knowing it. The implementation spins for some time before going for a full kernel mutex.

Re: Hell is a multi-threaded C++ program (2006)

#104
post #2

I've found message passing and thinking in transactions are pretty good architectural patterns for maintaining ones sanity. Message queues with spinlocks for performance critical code (mutexes are slow). The biggest sin generally is to disregard the overhead caused by thread management and thinking more threads makes the sofrware run faster. I've seen people try to parallellize a sequential program by just spawning m…

Is there a good message passing library for C++? Sounds like something for the stl to include.

> Is there a good message passing library for C++? Sounds like something for the stl to include.

Qt does it with signals-slots. What I generally do is that I have a queue of std::function and just pass lambdas with the capture being copied.

Re: Hell is a multi-threaded C++ program (2006)

#105

So to check, I googled C++11 threads memory model, and it[0] looks like his main complaint isn't helped by C++ 11 threads, as they essentially allow shared state too. They are also a thin veneer over the OS threads, for unix types, pthreads I imagine. [0] http://en.cppreference.com/w/cpp/language/memory_model

Yeah, I don't know if there's ever going to be a portable way to enforceably "disallow" the sharing of state between threads in C++. For straightforward cases, the SaferCPlusPlus library provides an easy way to "wrap" any object so that access from different threads is safely controlled[1]. [1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus#asynchronou...

> Yeah, I don't know if there's ever going to be a portable way to enforceably "disallow" the sharing of state between threads in C++.

Not sharing state at all means that you cannot even do message passing other than through sockets or something like this. At some point you have to share at least a message queue to be able to go from thread A to thread B.

Re: Hell is a multi-threaded C++ program (2006)

#106

Earlier quoted context omitted.

What is even more fundamental and useful than select is non-blocking reads (which the implementation I posted supports), once you have that you can write your own select. It's not magic, select has to traverse the list of channels just like any other code. The only reason it feels like magic in Go is that it's the only way to read a channel without blocking.

The non-blocking read parts is also easy, but that's also only one use-case for Go's select. The harder part is the generic "wait until one of the select cases can be taken". You can't implement this with non-blocking reads alone. If you would, it would be something like busy spinning and iterating through all select cases and trying none-blocking reads until one succeeds. But that's just not efficient. You need a me…

Adding a condition-variable per select and keeping a list of pointers in each channel that are pinged when data arrives is the easiest approach I can think of. Haven't tried that one though, I have honestly never run into a use case where I needed select for channels outside of Go.

Re: Hell is a multi-threaded C++ program (2006)

#107
post #12
post #4

> While standardization and support for [threaded] APIs has come a long way, their use is still predominantly restricted to system programmers as opposed to application programmers. One of the reasons for this is that APIs such as Pthreads are considered to be low-level primitives. Conventional wisdom indicates that a large class of applications can be efficiently supported by higher level constructs (or directives)…

Yes, every time I hear people talking about how evil or difficult threads are, I just think back to my frequent use of OpenMP. It is really quite easy to take a single-threaded program and make it multithreaded with OMP -- so long as the jobs only read, and do not write shared state. Usually I will write a program that does the following: 1. Initialize global read-only data structures 2. Parallelize jobs across STDIN…

Using OMP is incredibly easy but in my experience it sometimes leaves up to 20% performance on the table vs doing and tuning everything manually.

Re: Hell is a multi-threaded C++ program (2006)

#108

Earlier quoted context omitted.

> a system that will lead to unexpected bottlenecks when you parallelize This is a funny comment. You are implying that performance is of higher value than correctness. Speed without correctness is dangerous, and leads to significant bugs, especially when you're talking about concurrent modification of state across threads. I'll take correct and need to improve performance over incorrect and fast where the cost of tr…

> This is a funny comment. You are implying that performance is of higher value than correctness. Of course it is. Tony Hoare noticed it as far back as 1993: given a safe program and a fast program, people would always choose the fast one. Correctness in a mathematical sense does not always map to correctness in the business sense; it's sometimes much more cost-effective to reboot a computer every day and not free an…

In a case where it just crashes, that's probably a reasonable tradeoff.

What really bothers me though, is that you might actually store incorrect data somewhere. That could have hugely negative implications for the business.

Re: Hell is a multi-threaded C++ program (2006)

#109

I've been writing massively threaded C++ code since the 1990's, so I can comment with some serious experience here. My code used to run on 256CPU SGI's and had high cpu utilization across all of them. When designing C++ code for threading, you have to keep a few things in mind, but it's not particularly harder than on other languages with thread support. You generally want to create re-entrant functions which pass al…

In my limited experience of the single- to multi-threading circle of hell, the function calls performed outside of an effective form of closure are a bigger problem than globals / statics / singletons. Whenever an object is accessed concurrently by multiple threads, its state becomes a potential problem. Some programs may contain so many pathological dependencies that they cannot be multithreaded without introducing so much mutual exclusion that they cannot perform better than the single-threaded original, even if the task they implement is a candidate for multithreading. Putting those cases aside, the hardest part of conversion is probably that of understanding the existing code well enough to be able to find and analyze all the operations that cut across the thread boundaries created by the conversion, which are aspects of the dynamic behavior of the program.

Re: Hell is a multi-threaded C++ program (2006)

#110
post #10

Earlier quoted context omitted.

> spinlocks for performance critical code (mutexes are slow). Gah, no. Userspace spinlocks are the deepest of voodoo and something to be used only by people who know exactly what they are doing and would have no difficulty writing "traditional" threaded code in a C/C++ environment. Among other problems: what happens when the thread holding the spinlock gets preempted and something else runs on the core? How can you p…

> Gah, no. Userspace spinlocks are the deepest of voodoo and something to be used only by people who know exactly what they are doing and would have no difficulty writing "traditional" threaded code in a C/C++ environment. If you ever used pthread_mutex with glibc then you use spinlocks without knowing it. The implementation spins for some time before going for a full kernel mutex.

Sure, and C library authors qualify. App developers don't.
Post reply on HN