Risk Assessment: Using Pthreads (vs. GCD or NSThread)
Asked Answered
M

4

7

A colleague suggested recently that I use pthreads instead of GCD because it's, "way faster." I don't disagree that it's faster, but what's the risk with pthreads?

My feeling is that they will ultimately not be anywhere nearly as idiot-proof as GCD (and my team of one is 50% idiots). Are pthreads hard to get right?

Monopetalous answered 5/1, 2013 at 23:45 Comment(0)
M
13

GCD and pthreads are both ways of doing work asynchronously, but they are significantly different. Most descriptions of GCD describe it in terms of threads and of thread pooling, but as DrPizza puts it

to concentrate on [threads and thread pools] is to miss the point. GCD’s value lies not in thread pooling, but in queuing.
                                                                Grand Central Dispatch for Win32: why I want it

GCD has some nice benefits over APIs like pthreads.

  • GCD does more to encourage and support "islands of serialization in a sea of parallelism." GCD makes it easy to avoid a lot of locks and mutexes and condition variables that are the normal way of comunicating between threads. This is because you decompose your program into tasks and GCD handles getting the task input and output to the appropriate thread behind the scenes. So programming with GCD allows you to pretty much write serially and not worry too much about stuff people often worry about in threaded code. That makes the code simpler and less bug prone.

  • GCD can do scaling for you so the program uses as much parallelism as the dependencies between the tasks you've decomposed your program into and the hardware allow for. Of course designing the program to be scalable is generally the hard bit, but you'll still need something to actually take advantage of that work to run as much as possible in parallel. Work stealing schedulers like GCD do that part.

  • GCD is composable. If you explicitly spawn threads for things you want to do asynchronously or in parallel you can run into a problem when libraries you use do the same thing. Say you decide you can run eight threads simultaneously because that's how many threads will be effective for your program given the machine it runs on. And then say a library you use on each thread does the same thing. Now you could have up to 64 threads running at once, which is more than you know is effective for your program.

    Thread pooling solves this but everyone needs to use the same thread pool. GCD uses thread pooling internally and provides the same pool to everyone.

  • GCD provides a bunch of 'sources' and makes it easy to write an event driven program that depends on or takes input from the sources. For example you can very easily have a queue set up to launch a task every time data is available to read on a network socket, or when a timer fires, or whatever.

Monto answered 6/1, 2013 at 0:43 Comment(1)
+1 Great and really comprehensive answer. Thanks for taking the time to write this.Monopetalous
D
10

I don't think they're hard to get right, but having worked with many different approaches over the years (pthreads, GCD, NSThread, NSOperationQueue, etc.) I have no evidence to support an assertion like "pthreads are way faster." Even if they were faster (and I would expect the difference to be marginal at best) I always say, "use the highest level abstraction that gets the job done." Also, avoid pre-mature optimization.

Anecdotally speaking, GCD is pretty damn fast. How I see it, portability is the primary advantage of pthreads over GCD. If this is OSX/iOS exclusive code, I would see no advantage whatsoever to using pthreads, absent empirical evidence to the contrary.

Dove answered 6/1, 2013 at 0:3 Comment(3)
Agreed. I answered this question (citing stuff that's not mine, of course) on GCD being faster than NSThreads (tangentially related) #9238635Monopetalous
In my experience, GCD is awesomely f'in fast. I will pretty much stand by that assessment until I see incontrovertible empirical evidence to the contrary.Dove
Agreed. The next question is going to be about not using UILabel vs. CoreText if I can't find a good one. That one will have--fun!--memory implications as well.Monopetalous
E
3

Ignore the other well thought technical reasons, because they aren't relevant. You are not writing software for a benchmark, are you? At some point, a user is going to sit in front of your device and try to use it. And do you know what happens if you use pthreads instead of GCD? What happens is that your software doesn't scale well in the presence of other software multitasking at the same time because it is going to fight for the CPU presuming it is the only software running at the same time. Which is crazy. Nobody runs single task OSes any more. Even single task iOS runs much stuff in the background.

Instead, if all the programs you were running used GCD, the OS can scale the number of concurrent tasks running on their queues and thus match better the number of actual processors, reducing task switching overhead.

If your program doesn't require pseudo real time low latency and thus a dedicated thread to process stuff as soon as it is available (maybe the definition of your colleague's "way faster"), chances are GCD will be superior for the user because it will use better the resources available on their device. Even if GCD's API was horrible or slow it would be worthwhile to use it over other solutions which don't scale across different processes.

Ettore answered 20/3, 2014 at 9:1 Comment(0)
S
1

Probably NSThread is implemented using the pthreads library, the point is that the lower is the level of a concept, the more you have to do useless and repetitive tasks.

So the pthreads library isn't so hard to learn, my professor at university taught it, and even the most (call 'em so) slow at learning people were able to use the library, maybe randomly copying-pasting the code just for lazily but doing the job successfully.

So I definitely suggest you to implement a pthread wrapper class, it's easy to do it.

This way you eliminate the useless stuff, for example you may be doing this thousand of times:

pthread_mutex_init( mutex_ptr, NULL);

So (if that's your case, but it's just an example) you may be passing always NULL, and the same is valid for other functions.

Once implemented the class it isn't said that is faster than GCD.

GCD do some optimizations, for example two blocks may be ran in the same thread.

So I suggest to use your defined class only if it's faster than GCD, to test it with time profiler.

Shrivel answered 6/1, 2013 at 0:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.