No, Gfortran is very good. I think the problem is your 12th Gen Intel® Core™ i5-1235U.

Google search finds The i5–1235U is faster in tasks that use only 1–2 CPU cores or threads, such as photo editing. This is because the i5–1235U only has 2 high-performance CPU cores, its other 8 cores are much weaker “efficiency” cores.23 Dec 2023.

It is surprising there are only 2 performance cores, but 8 efficiency cores !
Then there is the problem with cooling with any recent Intel laptop.

Yes John, you are absolutely on the dot; it generates a lot of heat for which I have a cooling fan underneath.


Indeed. Not only the speed-up is reduced once Efficiency cores are used, but I think that OpenMP runtimes do not handle well (and maybe can’t handle well) the mix between performance and efficiency cores.

Moreover, this CPU has 10 physical cores (not 12) + 2 logical cores. When running with 12 threads the logical cores are used, but logical cores generally do not help speeding-up such computations.

Given all of this, the limited speed-up is not surprising.

Both are linked: more performance cores would result in more heating, and ultimately in automatic throttling (frequency downclocking) of the performance cores to reduce the temperature.

1 Like

On CPUs with Efficiency Cores, it would be worth trying the schedule(nonmonotonic:dynamic) clause in !$omp do . The dynamic schedule can help when the workload is not balanced between the threads (and maybe when the threads do not run on equally performant cores). The problem is that this schedule has more overheads than the default static one, but with the recent nonmonotonic modifier the overheads get very limited. But I’m not sure that gfortran supports it right now (recent versions of ifx do).


mojo run num_cpu_cores.mojo
Number of physical cores: 10
Number of logical cores: 12
Number of performance cores: 10

Is this mojo script:

from import num_physical_cores, num_logical_cores, num_performance_cores

fn main():
	print('Number of physical cores:',num_physical_cores())
	print('Number of logical cores:',num_logical_cores())
	print('Number of performance cores:', num_performance_cores())

being pedantic or wrong?

Definitely wrong (at least if your CPU is really an i5 1235U)

1 Like

Comes from here:


Architecture:                       x86_64
CPU op-mode(s):                     32-bit, 64-bit
Address sizes:                      39 bits physical, 48 bits virtual
Byte Order:                         Little Endian
CPU(s):                             12
On-line CPU(s) list:                0-11
Vendor ID:                          GenuineIntel
Model name:                         12th Gen Intel(R) Core(TM) i5-1235U
CPU family:                         6
Model:                              154

Given you have reported your program performance is topping out at 2 threads, this appears to be consistent with the google thread of only 2 performance cores, not “Number of performance cores: 10”

I have not had any experience with using “efficiency” cores for OpenMP, but assuming their instruction excludes avx instructions, I would think if using threads with such an imbalanced performance would exclude most of the computation types I have.

You could possibly try adding !$OMP& SCHEDULE (DYNAMIC)
that is assuming Gfortran -fopenmp even tries to use the other cores.

I have asked questions of if Gfortran or OpenMP implimentations utilise “efficiency” cores but never received a clear answer. !$OMP PARALLEL DO can be more sensitive to threads of different performance, so I don’t intend to try.

I currently use a Ryzen 5900X where I have turned off “2-way simultaneous multithreading”, as I get no benefit from the extra threads.
On my Intel 8700K, I also do not use hyper-threading, although most of my calculations are with large arrays where memory bandwidth might be the problem.

For multi-threaded computation, a desktop with adequate cooling could be a much better option. The AMD (nonX) processors running at a slower clock rate look to be a much better solution than an Intel room heater ! I wonder where the glossy marketed processors are taking us.

The Intel approach makes sense in a general-purpose laptop (e.g. not targeted at HPC), where the cooling capabilities are limited by the size of the laptop. The performance cores can handle peak computations demands for a short period of time, and the efficiency cores handle all background processes that are generally not very demanding.

Your Ryzen 5900X has a 105W TDP, which is much too high for most of the laptops.

Apple has here an edge with its Apple Silicon chips, which have a much better efficiency (flops/W) then the current x86 chips. A Macbook Pro can get better performances than equivalent x86 laptops, and without heating that much.

On a pseudo-server-grade PC we assembled it performs quite well doubling speed (again only till 4 performance cores):


Architecture:                       x86_64
CPU op-mode(s):                     32-bit, 64-bit
Address sizes:                      39 bits physical, 48 bits virtual
Byte Order:                         Little Endian
CPU(s):                             8
On-line CPU(s) list:                0-7
Vendor ID:                          GenuineIntel
Model name:                         Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
CPU family:                         6
Model:                              94

$mojo run num_cpu_cores.mojo

Number of physical cores: 4
Number of logical cores: 8
Number of performance cores: 4

$gfortran ...
Total run in seconds:
1 thread 16.3750
2 threads 8.3750
4 threads 4.4375
8 threads 3.8750

It looks like horses for courses:

With mojo SIMD arrays doing better on 12th Gen Interl-5 12-core Laptop CPUs,
while Fortran OpenMP doing well i7 6700 8-core PC CPUs