15

I would like to experiment with threads on a multi-core processor, e.g. to create a program that uses two different threads that are executed by two different processor cores.

However, it is not clear to me at which level the threads get allocated to the different cores. I can imagine the following scenarios (depending on operating system and programming language implementation):

  1. Thread allocation is managed by the operating system. Threads are created using OS system calls and, if the process happens to run on a multi-core processor, the OS automatically tries to allocate / schedule different threads on different cores.
  2. Thread allocation is managed by the programming language implementation. Allocating threads to different core requires special system calls, but the programming language standard thread libraries automatically handle this when I use the standard thread implementation for that language.
  3. Thread allocation must be programmed explicitly. In my program I have to write explicit code to detect how many cores are available and to allocate different threads to different core using, e.g., library functions.

To make the question more specific, imagine I have written my multi-threaded application in Java or C++ on Windows or Linux. Will my application magically see and use multiple cores when run on a multi-core processor (because everything is managed either by the operating system or by the standard thread library), or do I have to modify my code to be aware of the multiple cores?

2 Answers 2

14

Will my application magically see and use multiple cores when run on a multi-core processor (because everything is managed either by the operating system or by the standard thread library), or do I have to modify my code to be aware of the multiple cores?

Simple answer: Yes, it will usually be managed by the operating system or threading library.

The threading subsystem in the operating system will assign threads to processors on a priority basis (your option 1). In other words, when a thread has finished executing for its time allocation or blocks, the scheduler looks for the next highest priority thread and assigns that to the CPU. The details vary from operating system to operating system.

That said, options 2 (managed by programming language) and 3 (explicitly) exist. For example, the Tasks library and async/await in recent versions of .Net give the developer a much easier way to write parallelizable (i.e. that can run concurrently with itself) code. Functional programming languages are innately parallelizable and some runtimes will run different parts of the program in parallel if possible.

As for option 3 (explicitly), Windows allows you to set the thread affinity (specifying which processors a thread can run on). However, this is usually unnecessary in all but the fastest, response-time critical systems. Effective thread to processor allocation is highly hardware dependent and is very sensitive to other applications running concurrently.

If you want to experiment, create a long running, CPU intensive task like generating a list of prime numbers or creating a Mandelbrot set. Now create two threads in your favorite library and run both threads on a multi-processor machine (in other words, just about anything released in the last few years). Both tasks should complete in roughly the same time because they are run in parallel.

7
  • Thanks for the explanation (+1). My test program is a merge sort implementation. In the split phase, I want to create different threads as long as there are cores available. E.g., with two cores, each half of an array would get sorted by a different thread / core. During merge the superfluous threads would then be joined / terminated.
    – Giorgio
    Jan 1, 2013 at 12:07
  • Sorting is tough to parallelize in this way if the data is distributed randomly. Yes, you can break it up then sort each portion in a different thread but you eventually have to merge all the portions together, anyway. If the threads are sharing data structures, you may also get contention or locking issues. I am not saying sorting cannot benefit from threading but it will not be a linear performance improvement.
    – akton
    Jan 1, 2013 at 13:56
  • The two halves of an array can be sorted independently because no data is shared. Only the first split and the last merge will have to be performed by one thread manipulating the whole array or list containing the data. This means that one complete scan of the data cannot be executed in parallel; all remaining scans can.
    – Giorgio
    Jan 1, 2013 at 13:59
  • Of course, I also consider your examples as good candidates. I am just more familiar with merge sort at the moment (and I have implemented a non-parallel version of it), which would (maybe) make merge sort more suitable for me as a first attempt.
    – Giorgio
    Jan 1, 2013 at 14:02
  • 2
    I would add to this answer that good operating systems are smart enough to balance the cost of giving a task a time slice on a different CPU or core with that of short-term starvation. On architectures where it matters, the result tends to resemble automagic affinity. The OS has been built around getting all jobs run as quickly as possible, and you may be shooting yourself in the foot by tying threads to cores and hamstringing its ability to make those decisions.
    – Blrfl
    Jan 1, 2013 at 14:07
-1

I once had a huge SGI IRIX environment. Just for the heck of it, I wrote a small multi-threaded java program(which just did nothing but consume CPU cycles) and created 12 threads in it. The job spanned across 12 CPUs in NUMA architecture. May be I will look up the program and run it on the Dell R910s and check..

1
  • 3
    This answer really doesn't add much to the existing answer. Perhaps if you elaborated on why the JVM on the SGI system allocated threads to core...
    – Jay Elston
    Mar 21, 2015 at 18:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.