[libgomp,testsuite] Generalize getconf _NPROCESSORS_ONLN

Message ID yddh89d9wmi.fsf@CeBiTec.Uni-Bielefeld.DE
State New
Headers show
Series
  • [libgomp,testsuite] Generalize getconf _NPROCESSORS_ONLN
Related show

Commit Message

Rainer Orth May 29, 2019, 2:13 p.m.
Prompted by extremely long libgomp make check times due to missing
parallelism, I noticed that the current support to restrict testcase
parallelism only works on targets which have getconf _NPROCESSORS_ONLN.
Instead of adding special cases for all sorts of tools to determine the
number of cores, I found a macro in the autoconf-archive that
encapsulates just that.

The following patch makes use of that, bootstrapped without regressions
on i386-pc-solaris2.11 and sparc-sun-solaris2.11 and checked that
CPU_COUNT is determined correctly and the OMP_NUMP_THREADS warning
emitted.  Also rebuilt libgomp on x86_64-pc-linux-gnu and performed the
same check.

Ok for mainline?

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University


2019-05-28  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	libgomp:
	* configure.ac: Call AX_COUNT_CPUS.
	Substitute CPU_COUNT.
	* testsuite/Makefile.am (check-am): Use CPU_COUNT as processor count.
	* aclocal.m4: Regenerate.
	* configure: Regenerate.
	* Makefile.in, testsuite/Makefile.in: Regenerate.

	config:
	* ax_count_cpus.m4: New file.

Comments

Jakub Jelinek May 29, 2019, 2:23 p.m. | #1
On Wed, May 29, 2019 at 04:13:41PM +0200, Rainer Orth wrote:
> Prompted by extremely long libgomp make check times due to missing

> parallelism, I noticed that the current support to restrict testcase

> parallelism only works on targets which have getconf _NPROCESSORS_ONLN.

> Instead of adding special cases for all sorts of tools to determine the

> number of cores, I found a macro in the autoconf-archive that

> encapsulates just that.

> 

> The following patch makes use of that, bootstrapped without regressions

> on i386-pc-solaris2.11 and sparc-sun-solaris2.11 and checked that

> CPU_COUNT is determined correctly and the OMP_NUMP_THREADS warning

> emitted.  Also rebuilt libgomp on x86_64-pc-linux-gnu and performed the

> same check.

> 

> Ok for mainline?


I'd prefer not to determine the CPU count at configure time, the build
directory can be on some network filesystem and tested sometimes on one
machine, sometimes on another one, hw can be upgraded etc.
So, something similar to what your patch does, but don't substitute the actual
CPU count, but a command to determine the number of CPUs?

	Jakub
Rainer Orth May 29, 2019, 2:32 p.m. | #2
Hi Jakub,

> On Wed, May 29, 2019 at 04:13:41PM +0200, Rainer Orth wrote:

>> Prompted by extremely long libgomp make check times due to missing

>> parallelism, I noticed that the current support to restrict testcase

>> parallelism only works on targets which have getconf _NPROCESSORS_ONLN.

>> Instead of adding special cases for all sorts of tools to determine the

>> number of cores, I found a macro in the autoconf-archive that

>> encapsulates just that.

>> 

>> The following patch makes use of that, bootstrapped without regressions

>> on i386-pc-solaris2.11 and sparc-sun-solaris2.11 and checked that

>> CPU_COUNT is determined correctly and the OMP_NUMP_THREADS warning

>> emitted.  Also rebuilt libgomp on x86_64-pc-linux-gnu and performed the

>> same check.

>> 

>> Ok for mainline?

>

> I'd prefer not to determine the CPU count at configure time, the build

> directory can be on some network filesystem and tested sometimes on one

> machine, sometimes on another one, hw can be upgraded etc.


somewhat agreed for testing on one or the other system.  However, build
dirs tend to be short-lived in my experience (and usually local because
at least I have found builds on NFS so incredibly slow as to avoid them
like the plague) and hw upgrades are relatively rare.

> So, something similar to what your patch does, but don't substitute the actual

> CPU count, but a command to determine the number of CPUs?


I'm not convinced that would work reliably: you can easily have one set
of commands on one machine, but a slightly different one on another.  If
we really want to go this route, that means extracting the autoconf
macro's logic into a separate script and use that at make check time.
Not sure if that's worth the effort, especially since we're not really
interested in the exact number of cores, just small (<= 8) vs. large (> 8).

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Jakub Jelinek May 29, 2019, 2:46 p.m. | #3
On Wed, May 29, 2019 at 04:32:41PM +0200, Rainer Orth wrote:
> > I'd prefer not to determine the CPU count at configure time, the build

> > directory can be on some network filesystem and tested sometimes on one

> > machine, sometimes on another one, hw can be upgraded etc.

> 

> somewhat agreed for testing on one or the other system.  However, build

> dirs tend to be short-lived in my experience (and usually local because

> at least I have found builds on NFS so incredibly slow as to avoid them

> like the plague) and hw upgrades are relatively rare.

> 

> > So, something similar to what your patch does, but don't substitute the actual

> > CPU count, but a command to determine the number of CPUs?

> 

> I'm not convinced that would work reliably: you can easily have one set

> of commands on one machine, but a slightly different one on another.  If

> we really want to go this route, that means extracting the autoconf

> macro's logic into a separate script and use that at make check time.

> Not sure if that's worth the effort, especially since we're not really

> interested in the exact number of cores, just small (<= 8) vs. large (> 8).


Ok, so can we do a middle-ground, instead of the current change to
Makefile.am just replace the two spots that do num_cpus=1 with num_cpus=@CPU_COUNT@
and keep the getconf invocation in there?  On Linux it will do what it used
to do, and on targets that don't support getconf _NPROCESSORS_ONLN it will
use a configure time determined value?

	Jakub
Rainer Orth May 29, 2019, 2:51 p.m. | #4
Hi Jakub,

>> > So, something similar to what your patch does, but don't substitute the

>> > actual

>> > CPU count, but a command to determine the number of CPUs?

>> 

>> I'm not convinced that would work reliably: you can easily have one set

>> of commands on one machine, but a slightly different one on another.  If

>> we really want to go this route, that means extracting the autoconf

>> macro's logic into a separate script and use that at make check time.

>> Not sure if that's worth the effort, especially since we're not really

>> interested in the exact number of cores, just small (<= 8) vs. large (> 8).

>

> Ok, so can we do a middle-ground, instead of the current change to

> Makefile.am just replace the two spots that do num_cpus=1 with

> num_cpus=@CPU_COUNT@

> and keep the getconf invocation in there?  On Linux it will do what it used

> to do, and on targets that don't support getconf _NPROCESSORS_ONLN it will

> use a configure time determined value?


fine with me.  I'll send an updated patch after testing.

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Rainer Orth May 30, 2019, 8:59 a.m. | #5
Hi Jakub,

>>> > So, something similar to what your patch does, but don't substitute the

>>> > actual

>>> > CPU count, but a command to determine the number of CPUs?

>>> 

>>> I'm not convinced that would work reliably: you can easily have one set

>>> of commands on one machine, but a slightly different one on another.  If

>>> we really want to go this route, that means extracting the autoconf

>>> macro's logic into a separate script and use that at make check time.

>>> Not sure if that's worth the effort, especially since we're not really

>>> interested in the exact number of cores, just small (<= 8) vs. large (> 8).

>>

>> Ok, so can we do a middle-ground, instead of the current change to

>> Makefile.am just replace the two spots that do num_cpus=1 with

>> num_cpus=@CPU_COUNT@

>> and keep the getconf invocation in there?  On Linux it will do what it used

>> to do, and on targets that don't support getconf _NPROCESSORS_ONLN it will

>> use a configure time determined value?

>

> fine with me.  I'll send an updated patch after testing.


this version does this and passed the same testing as the previous one.
Ok for mainline now?

Thanks.
        Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University


2019-05-28  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	libgomp:
	* configure.ac: Call AX_COUNT_CPUS.
	Substitute CPU_COUNT.
	* testsuite/Makefile.am (check-am): Use CPU_COUNT as processor
	count fallback.
	* aclocal.m4: Regenerate.
	* configure: Regenerate.
	* Makefile.in, testsuite/Makefile.in: Regenerate.

	config:
	* ax_count_cpus.m4: New file.
# HG changeset patch
# Parent  af986e73ea19567ed6d9553b898d7e3d475a528f
Generalize getconf _NPROCESSORS_ONLN

diff --git a/config/ax_count_cpus.m4 b/config/ax_count_cpus.m4
new file mode 100644
--- /dev/null
+++ b/config/ax_count_cpus.m4
@@ -0,0 +1,101 @@
+# ===========================================================================
+#      https://www.gnu.org/software/autoconf-archive/ax_count_cpus.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COUNT_CPUS([ACTION-IF-DETECTED],[ACTION-IF-NOT-DETECTED])
+#
+# DESCRIPTION
+#
+#   Attempt to count the number of logical processor cores (including
+#   virtual and HT cores) currently available to use on the machine and
+#   place detected value in CPU_COUNT variable.
+#
+#   On successful detection, ACTION-IF-DETECTED is executed if present. If
+#   the detection fails, then ACTION-IF-NOT-DETECTED is triggered. The
+#   default ACTION-IF-NOT-DETECTED is to set CPU_COUNT to 1.
+#
+# LICENSE
+#
+#   Copyright (c) 2014,2016 Karlson2k (Evgeny Grin) <k2k@narod.ru>
+#   Copyright (c) 2012 Brian Aker <brian@tangent.org>
+#   Copyright (c) 2008 Michael Paul Bailey <jinxidoru@byu.net>
+#   Copyright (c) 2008 Christophe Tournayre <turn3r@users.sourceforge.net>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 22
+
+  AC_DEFUN([AX_COUNT_CPUS],[dnl
+      AC_REQUIRE([AC_CANONICAL_HOST])dnl
+      AC_REQUIRE([AC_PROG_EGREP])dnl
+      AC_MSG_CHECKING([the number of available CPUs])
+      CPU_COUNT="0"
+
+      # Try generic methods
+
+      # 'getconf' is POSIX utility, but '_NPROCESSORS_ONLN' and
+      # 'NPROCESSORS_ONLN' are platform-specific
+      command -v getconf >/dev/null 2>&1 && \
+        CPU_COUNT=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null` || CPU_COUNT="0"
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v nproc >/dev/null 2>&1]],[[: # empty]],[dnl
+        # 'nproc' is part of GNU Coreutils and is widely available
+        CPU_COUNT=`OMP_NUM_THREADS='' nproc 2>/dev/null` || CPU_COUNT=`nproc 2>/dev/null` || CPU_COUNT="0"
+      ])dnl
+
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl
+        # Try platform-specific preferred methods
+        AS_CASE([[$host_os]],dnl
+          [[*linux*]],[[CPU_COUNT=`lscpu -p 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+,' -c` || CPU_COUNT="0"]],dnl
+          [[*darwin*]],[[CPU_COUNT=`sysctl -n hw.logicalcpu 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[freebsd*]],[[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n kern.smp.cpus 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[netbsd*]], [[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n hw.ncpuonline 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[solaris*]],[[command -v psrinfo >/dev/null 2>&1 && CPU_COUNT=`psrinfo 2>/dev/null | $EGREP -e '^@<:@0-9@:>@.*on-line' -c 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[mingw*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl
+          [[msys*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl
+          [[cygwin*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]]dnl
+        )dnl
+      ])dnl
+
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v sysctl >/dev/null 2>&1]],[[: # empty]],[dnl
+        # Try less preferred generic method
+        # 'hw.ncpu' exist on many platforms, but not on GNU/Linux
+        CPU_COUNT=`sysctl -n hw.ncpu 2>/dev/null` || CPU_COUNT="0"
+      ])dnl
+
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl
+      # Try platform-specific fallback methods
+      # They can be less accurate and slower then preferred methods
+        AS_CASE([[$host_os]],dnl
+          [[*linux*]],[[CPU_COUNT=`$EGREP -e '^processor' -c /proc/cpuinfo 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[*darwin*]],[[CPU_COUNT=`system_profiler SPHardwareDataType 2>/dev/null | $EGREP -i -e 'number of cores:'|cut -d : -f 2 -s|tr -d ' '` || CPU_COUNT="0"]],dnl
+          [[freebsd*]],[[CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+: '|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl
+          [[netbsd*]], [[CPU_COUNT=`command -v cpuctl >/dev/null 2>&1 && cpuctl list 2>/dev/null| $EGREP -e '^@<:@0-9@:>@+ .* online ' -c` || \
+                           CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+ at'|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl
+          [[solaris*]],[[command -v kstat >/dev/null 2>&1 && CPU_COUNT=`kstat -m cpu_info -s state -p 2>/dev/null | $EGREP -c -e 'on-line'` || \
+                           CPU_COUNT=`kstat -m cpu_info 2>/dev/null | $EGREP -c -e 'module: cpu_info'` || CPU_COUNT="0"]],dnl
+          [[mingw*]],[AS_IF([[CPU_COUNT=`reg query 'HKLM\\Hardware\\Description\\System\\CentralProcessor' 2>/dev/null | $EGREP -e '\\\\@<:@0-9@:>@+$' -c`]],dnl
+                        [[: # empty]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]])],dnl
+          [[msys*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]],dnl
+          [[cygwin*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]]dnl
+        )dnl
+      ])dnl
+
+      AS_IF([[test "x$CPU_COUNT" != "x0" && test "$CPU_COUNT" -gt 0 2>/dev/null]],[dnl
+          AC_MSG_RESULT([[$CPU_COUNT]])
+          m4_ifvaln([$1],[$1],)dnl
+        ],[dnl
+          m4_ifval([$2],[dnl
+            AS_UNSET([[CPU_COUNT]])
+            AC_MSG_RESULT([[unable to detect]])
+            $2
+          ], [dnl
+            CPU_COUNT="1"
+            AC_MSG_RESULT([[unable to detect (assuming 1)]])
+          ])dnl
+        ])dnl
+      ])dnl
diff --git a/libgomp/configure.ac b/libgomp/configure.ac
--- a/libgomp/configure.ac
+++ b/libgomp/configure.ac
@@ -318,6 +318,10 @@ if test $enable_symvers = gnu; then
 	    [Define to 1 if GNU symbol versioning is used for libgomp.])
 fi
 
+# Determine cpu count to limit testsuite parallelism.
+AX_COUNT_CPUS
+AC_SUBST(CPU_COUNT)
+
 # Get target configury.
 . ${srcdir}/configure.tgt
 CFLAGS="$save_CFLAGS $XCFLAGS"
diff --git a/libgomp/testsuite/Makefile.am b/libgomp/testsuite/Makefile.am
--- a/libgomp/testsuite/Makefile.am
+++ b/libgomp/testsuite/Makefile.am
@@ -69,11 +69,11 @@ distclean-DEJAGNU:
 distclean-am: distclean-DEJAGNU
 check-am:
 	@if test -n "$(filter -j%, $(MFLAGS))"; then \
-	  num_cpus=1; \
+	  num_cpus=@CPU_COUNT@; \
 	  if type -p getconf 2>/dev/null >/dev/null; then \
 	    num_cpus=`getconf _NPROCESSORS_ONLN 2>/dev/null`; \
 	    case "$$num_cpus" in \
-	      '' | 0* | *[!0-9]*) num_cpus=1;; \
+	      '' | 0* | *[!0-9]*) num_cpus=@CPU_COUNT@;; \
 	    esac; \
 	  fi; \
 	  if test $$num_cpus -gt 8 && test -z "$$OMP_NUM_THREADS"; then \
Jakub Jelinek May 30, 2019, 9:02 a.m. | #6
On Thu, May 30, 2019 at 10:59:59AM +0200, Rainer Orth wrote:
> this version does this and passed the same testing as the previous one.

> Ok for mainline now?

> 

> Thanks.

>         Rainer

> 

> -- 

> -----------------------------------------------------------------------------

> Rainer Orth, Center for Biotechnology, Bielefeld University

> 

> 

> 2019-05-28  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

> 

> 	libgomp:

> 	* configure.ac: Call AX_COUNT_CPUS.

> 	Substitute CPU_COUNT.

> 	* testsuite/Makefile.am (check-am): Use CPU_COUNT as processor

> 	count fallback.

> 	* aclocal.m4: Regenerate.

> 	* configure: Regenerate.

> 	* Makefile.in, testsuite/Makefile.in: Regenerate.

> 

> 	config:

> 	* ax_count_cpus.m4: New file.


Ok, thanks.

	Jakub

Patch

# HG changeset patch
# Parent  26461208f9155e138ea93c5cb2979247de995b40
Generalize getconf _NPROCESSORS_ONLN

	libgomp:
	* configure.ac: Call AX_COUNT_CPUS.
	Substitute CPU_COUNT.
	* testsuite/Makefile.am (check-am): Use CPU_COUNT as processor count.
	* aclocal.m4: Regenerate.
	* configure: Regenerate.
	* Makefile.in, testsuite/Makefile.in: Regenerate.

	config:
	* ax_count_cpus.m4: New file.

diff --git a/config/ax_count_cpus.m4 b/config/ax_count_cpus.m4
new file mode 100644
--- /dev/null
+++ b/config/ax_count_cpus.m4
@@ -0,0 +1,101 @@ 
+# ===========================================================================
+#      https://www.gnu.org/software/autoconf-archive/ax_count_cpus.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COUNT_CPUS([ACTION-IF-DETECTED],[ACTION-IF-NOT-DETECTED])
+#
+# DESCRIPTION
+#
+#   Attempt to count the number of logical processor cores (including
+#   virtual and HT cores) currently available to use on the machine and
+#   place detected value in CPU_COUNT variable.
+#
+#   On successful detection, ACTION-IF-DETECTED is executed if present. If
+#   the detection fails, then ACTION-IF-NOT-DETECTED is triggered. The
+#   default ACTION-IF-NOT-DETECTED is to set CPU_COUNT to 1.
+#
+# LICENSE
+#
+#   Copyright (c) 2014,2016 Karlson2k (Evgeny Grin) <k2k@narod.ru>
+#   Copyright (c) 2012 Brian Aker <brian@tangent.org>
+#   Copyright (c) 2008 Michael Paul Bailey <jinxidoru@byu.net>
+#   Copyright (c) 2008 Christophe Tournayre <turn3r@users.sourceforge.net>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 22
+
+  AC_DEFUN([AX_COUNT_CPUS],[dnl
+      AC_REQUIRE([AC_CANONICAL_HOST])dnl
+      AC_REQUIRE([AC_PROG_EGREP])dnl
+      AC_MSG_CHECKING([the number of available CPUs])
+      CPU_COUNT="0"
+
+      # Try generic methods
+
+      # 'getconf' is POSIX utility, but '_NPROCESSORS_ONLN' and
+      # 'NPROCESSORS_ONLN' are platform-specific
+      command -v getconf >/dev/null 2>&1 && \
+        CPU_COUNT=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null` || CPU_COUNT="0"
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v nproc >/dev/null 2>&1]],[[: # empty]],[dnl
+        # 'nproc' is part of GNU Coreutils and is widely available
+        CPU_COUNT=`OMP_NUM_THREADS='' nproc 2>/dev/null` || CPU_COUNT=`nproc 2>/dev/null` || CPU_COUNT="0"
+      ])dnl
+
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl
+        # Try platform-specific preferred methods
+        AS_CASE([[$host_os]],dnl
+          [[*linux*]],[[CPU_COUNT=`lscpu -p 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+,' -c` || CPU_COUNT="0"]],dnl
+          [[*darwin*]],[[CPU_COUNT=`sysctl -n hw.logicalcpu 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[freebsd*]],[[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n kern.smp.cpus 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[netbsd*]], [[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n hw.ncpuonline 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[solaris*]],[[command -v psrinfo >/dev/null 2>&1 && CPU_COUNT=`psrinfo 2>/dev/null | $EGREP -e '^@<:@0-9@:>@.*on-line' -c 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[mingw*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl
+          [[msys*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl
+          [[cygwin*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]]dnl
+        )dnl
+      ])dnl
+
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v sysctl >/dev/null 2>&1]],[[: # empty]],[dnl
+        # Try less preferred generic method
+        # 'hw.ncpu' exist on many platforms, but not on GNU/Linux
+        CPU_COUNT=`sysctl -n hw.ncpu 2>/dev/null` || CPU_COUNT="0"
+      ])dnl
+
+      AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl
+      # Try platform-specific fallback methods
+      # They can be less accurate and slower then preferred methods
+        AS_CASE([[$host_os]],dnl
+          [[*linux*]],[[CPU_COUNT=`$EGREP -e '^processor' -c /proc/cpuinfo 2>/dev/null` || CPU_COUNT="0"]],dnl
+          [[*darwin*]],[[CPU_COUNT=`system_profiler SPHardwareDataType 2>/dev/null | $EGREP -i -e 'number of cores:'|cut -d : -f 2 -s|tr -d ' '` || CPU_COUNT="0"]],dnl
+          [[freebsd*]],[[CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+: '|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl
+          [[netbsd*]], [[CPU_COUNT=`command -v cpuctl >/dev/null 2>&1 && cpuctl list 2>/dev/null| $EGREP -e '^@<:@0-9@:>@+ .* online ' -c` || \
+                           CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+ at'|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl
+          [[solaris*]],[[command -v kstat >/dev/null 2>&1 && CPU_COUNT=`kstat -m cpu_info -s state -p 2>/dev/null | $EGREP -c -e 'on-line'` || \
+                           CPU_COUNT=`kstat -m cpu_info 2>/dev/null | $EGREP -c -e 'module: cpu_info'` || CPU_COUNT="0"]],dnl
+          [[mingw*]],[AS_IF([[CPU_COUNT=`reg query 'HKLM\\Hardware\\Description\\System\\CentralProcessor' 2>/dev/null | $EGREP -e '\\\\@<:@0-9@:>@+$' -c`]],dnl
+                        [[: # empty]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]])],dnl
+          [[msys*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]],dnl
+          [[cygwin*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]]dnl
+        )dnl
+      ])dnl
+
+      AS_IF([[test "x$CPU_COUNT" != "x0" && test "$CPU_COUNT" -gt 0 2>/dev/null]],[dnl
+          AC_MSG_RESULT([[$CPU_COUNT]])
+          m4_ifvaln([$1],[$1],)dnl
+        ],[dnl
+          m4_ifval([$2],[dnl
+            AS_UNSET([[CPU_COUNT]])
+            AC_MSG_RESULT([[unable to detect]])
+            $2
+          ], [dnl
+            CPU_COUNT="1"
+            AC_MSG_RESULT([[unable to detect (assuming 1)]])
+          ])dnl
+        ])dnl
+      ])dnl
diff --git a/libgomp/configure.ac b/libgomp/configure.ac
--- a/libgomp/configure.ac
+++ b/libgomp/configure.ac
@@ -318,6 +318,10 @@  if test $enable_symvers = gnu; then
 	    [Define to 1 if GNU symbol versioning is used for libgomp.])
 fi
 
+# Determine cpu count to limit testsuite parallelism.
+AX_COUNT_CPUS
+AC_SUBST(CPU_COUNT)
+
 # Get target configury.
 . ${srcdir}/configure.tgt
 CFLAGS="$save_CFLAGS $XCFLAGS"
diff --git a/libgomp/testsuite/Makefile.am b/libgomp/testsuite/Makefile.am
--- a/libgomp/testsuite/Makefile.am
+++ b/libgomp/testsuite/Makefile.am
@@ -69,14 +69,7 @@  distclean-DEJAGNU:
 distclean-am: distclean-DEJAGNU
 check-am:
 	@if test -n "$(filter -j%, $(MFLAGS))"; then \
-	  num_cpus=1; \
-	  if type -p getconf 2>/dev/null >/dev/null; then \
-	    num_cpus=`getconf _NPROCESSORS_ONLN 2>/dev/null`; \
-	    case "$$num_cpus" in \
-	      '' | 0* | *[!0-9]*) num_cpus=1;; \
-	    esac; \
-	  fi; \
-	  if test $$num_cpus -gt 8 && test -z "$$OMP_NUM_THREADS"; then \
+	  if test @CPU_COUNT@ -gt 8 && test -z "$$OMP_NUM_THREADS"; then \
 	    OMP_NUM_THREADS=8; export OMP_NUM_THREADS; \
 	    echo @@@ libgomp OMP_NUM_THREADS adjusted to 8 because of parallel make check and too many CPUs; \
 	  fi; \