# Threads vs Cores: How many kernels need to launch in parallel Mathematica?

I have a dual-core intel machine. I would like to test how many parallel local kernels should be launch to get the optimized performance. Knowing that the HyperThreading technology of Intel could run 2 "Threads" on 1 core. That means we could run 4 threads on a dual-core CPU. For informations about "Threads vs Cores", look at here.. AMD says "no" to HyperThreading, and after them, cores is much more important. view amd vs intel: "Based on the results of the Cinebench® and PovRay® benchmark tests, we find that physical cores outperform enhanced threading software in certain applications."

Function to evaluate:

mlength[z_] :=
Length[FixedPointList[#^2 + z &, z, 20, SameTest -> (Abs[#] > 2 &)]]


1. Sequential Evaluation (No parallel)

CloseKernels[]; Kernels[]
ParallelTable[
mlength[x + I y], {y, -1, 1, 0.005}, {x, -2, 1,
0.005}]; // AbsoluteTiming


During evaluation of ParallelTable::nopar: No parallel kernels available; proceeding with sequential evaluation.

{8.814056, Null}

Although no parallel kernel is used, we can see that the second core on the right shares about 50% the work with the first core. I think Windows automatically shares the work for multicore.

2. Using 1 Slave kernel

CloseKernels[]; LaunchKernels[1]; Kernels[]
ParallelTable[
mlength[x + I y], {y, -1, 1, 0.005}, {x, -2, 1,
0.005}]; // AbsoluteTiming


{9.110458, Null}

By asking Mathematica add one slave kernel, this slave kernel runs on the first core mainly (on the left) and we can see that the work is mainly done in the first core. There are still some works on the second core.

3. Using 2 slaves kernel

CloseKernels[]; LaunchKernels[2]; Kernels[]
ParallelTable[
mlength[x + I y], {y, -1, 1, 0.005}, {x, -2, 1,
0.005}]; // AbsoluteTiming


{4.820431, Null}

Now, with 2 slaves kernels, the work is evenly distributed on 2 cores. That's the reason why, we get the results done in half of the time. We can see that Mathematica parallelizes better than Windows.

4.Using 4 slaves kernel

CloseKernels[]; LaunchKernels[4]; Kernels[]
ParallelTable[
mlength[x + I y], {y, -1, 1, 0.005}, {x, -2, 1,
0.005}]; // AbsoluteTiming


{5.023232, Null}

I'm trying to add more kernels by supposing that, one core could maintain 2 "threads". But the results is slower. I think Multithreading does not help in Mathematica. So the rule of thumb is: the number of parallel local kernels = number of cores (not threads). Increasing number of kernel just increases the overhead of data transfer between kernels.

Any suggestions?

=================================================================

Udate to another computer Intel i7, 4 CORES, 8 THREADS (TRUE HT).

maxKernel = 8;
data = Table[
CloseKernels[];
LaunchKernels[n];
ParallelTable[
mlength[x + I y], {y, -2, 1, 0.002}, {x, -2, 1, 0.002}]; //
AbsoluteTiming // First, {n, 0, maxKernel}]


{40.332307, 44.634553, 22.154267, 17.925025, 14.795846, 13.280760, \ 12.369708, 13.218756, 12.701726}

We can see that, the time decreases up to 4 Cores, and then, up to 6 threads, time optimized only 1-2 second.

-
HT is not a solution when your task is mostly compute-intensive, and most M tasks, especially when done in parallel, are done for compute purposes. When two threads run over the same core, they still share the same ALU, load/store units, etc. HT is great when you have to handle a lot of objects, for example for webservers, where you handle a lot of connection objects, request objects, etc. But for compute-intensive applications, HT gives you only a very small improvement, namely to the extent that the parallel threads don't use the same ALU -- and there is very little of that. –  Andreas Lauschke Dec 17 '13 at 17:18
For compute-intensive tasks, every thread needs its own ALU, and HT doesn't give you that. You have turned 4 physical cores into 8 virtual cores, but you haven't doubled the number of ALUs. You're almost back at square 1. I have done a lot of this type of benchmarking, and in my own comparisons turning HT on improved execution times 5 - 10% compared to the runs when I had turned HT off. –  Andreas Lauschke Dec 17 '13 at 17:20
@AndreasLauschke SMT (a.k.a. HT) is very good for hiding cache miss latency (this being actually its main reason for existing). For applications with large, poorly localized working sets, such as symbolic calculations in Mathematica, SMT should be quite helpful. Its efficacy does of course depend on the specific calculation being attempted. –  Oleksandr R. Dec 18 '13 at 2:43
Be careful when taking AMD's marketing literature at face value. Their "cores" are actually less than an Intel core since the front end and FP logic are shared in groups of two. One could just as well call two of AMD's "cores" one core; the distinction AMD is trying to make is pure marketing and tends to be confusing when reasoning about actual performance. Their approach has some advantages, yes, but some disadvantages as well. –  Oleksandr R. Dec 18 '13 at 2:52
@AndreasLauschke I think that such language tends to obfuscate the issue. Better to consider whether the calculations being performed involve a lot of pointer chasing, or if they're more memory bandwidth limited. Numerical computations are not always disadvantaged by using SMT--for instance, ray tracing involves a lot of unpredictable branches and gains a substantial benefit from it. Typical numerical code (not something highly optimized, like MKL function calls) generally is not very memory bandwidth-efficient. I think the slowdown in the 4-thread case is mainly due to PCT overhead, actually. –  Oleksandr R. Dec 18 '13 at 13:52