Feature #10267 » etc-nprocessors-kosaki2.patch
ChangeLog | ||
---|---|---|
Thu Oct 2 05:50:59 2014 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
|
||
* ext/etc/etc.c (etc_nprocessors_affinity): use sched_getaffinity
|
||
for getting precious number of available cpus.
|
||
* ext/etc/etc.c (etc_nprocessors): use etc_nprocessors_affinity if
|
||
possible.
|
||
Thu Oct 2 03:42:12 2014 Tanaka Akira <akr@fsij.org>
|
||
* ext/etc/etc.c (etc_nprocessors_online): New method.
|
configure.in | ||
---|---|---|
AC_CHECK_FUNCS(qsort_r)
|
||
AC_CHECK_FUNCS(readlink)
|
||
AC_CHECK_FUNCS(round)
|
||
AC_CHECK_FUNCS(sched_getaffinity)
|
||
AC_CHECK_FUNCS(seekdir)
|
||
AC_CHECK_FUNCS(select_large_fdset)
|
||
AC_CHECK_FUNCS(sendfile)
|
ext/etc/etc.c | ||
---|---|---|
#include <sys/utsname.h>
|
||
#endif
|
||
#ifdef HAVE_SCHED_GETAFFINITY
|
||
#include <sched.h>
|
||
#endif
|
||
static VALUE sPasswd;
|
||
#ifdef HAVE_GETGRENT
|
||
static VALUE sGroup;
|
||
... | ... | |
#define io_pathconf rb_f_notimplement
|
||
#endif
|
||
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
|
||
#ifdef HAVE_SCHED_GETAFFINITY
|
||
static int
|
||
etc_nprocessors_affin(void)
|
||
{
|
||
cpu_set_t *cpuset;
|
||
size_t size;
|
||
int ret;
|
||
int ncpus;
|
||
/*
|
||
* XXX:
|
||
* man page says CPU_ALLOC takes number of cpus. But it is not accurate
|
||
* explanation. sched_getaffinity() returns EINVAL if cpuset bitmap is
|
||
* smaller than kernel internal bitmap.
|
||
* That said, sched_getaffinity() can fail when a kernel have sparse bitmap
|
||
* even if cpuset bitmap is larger than number of cpus.
|
||
* The precious way is to use /sys/devices/system/cpu/online. But there are
|
||
* two problems,
|
||
* - Costly calculation
|
||
* It is minor issue, but possibly kill the benefit of parallel processing.
|
||
* - No guarantee to exist /sys/devices/system/cpu/online
|
||
* This is an issue especially when using containers.
|
||
* So, we use hardcode number for workaround. Current linux kernel
|
||
* (Linux 3.17) support 8192 cpus at maximum. Then 16384 is enough large.
|
||
*/
|
||
ncpus = 16384;
|
||
cpuset = CPU_ALLOC(ncpus);
|
||
if (!cpuset) {
|
||
return -1
|
||
}
|
||
size = CPU_ALLOC_SIZE(ncpus);
|
||
CPU_ZERO_S(size, cpuset);
|
||
ret = sched_getaffinity(0, size, cpuset);
|
||
if (ret==-1) {
|
||
goto free;
|
||
}
|
||
ret = CPU_COUNT_S(size, cpuset);
|
||
free:
|
||
CPU_FREE(cpuset);
|
||
return ret;
|
||
}
|
||
#endif
|
||
/*
|
||
* Returns the number of online processors.
|
||
*
|
||
... | ... | |
*
|
||
* This method is implemented as:
|
||
* - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX
|
||
* - sched_getaffinity(): Linux
|
||
*
|
||
* Example:
|
||
*
|
||
* require 'etc'
|
||
* p Etc.nprocessors #=> 4
|
||
*
|
||
* The result might be smaller number than physical cpus especially when ruby
|
||
* process is bound to specific cpus. This is intended for getting better
|
||
* parallel processing.
|
||
*
|
||
* Example: (Linux)
|
||
*
|
||
* $ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2
|
||
*
|
||
*/
|
||
static VALUE
|
||
etc_nprocessors(VALUE obj)
|
||
{
|
||
long ret;
|
||
#ifdef HAVE_SCHED_GETAFFINITY
|
||
int ncpus;
|
||
ncpus = etc_nprocessors_affin();
|
||
if (ncpus != -1) {
|
||
return INT2NUM(ncpus);
|
||
}
|
||
/* fallback to _SC_NPROCESSORS_ONLN */
|
||
#endif
|
||
errno = 0;
|
||
ret = sysconf(_SC_NPROCESSORS_ONLN);
|
||
if (ret == -1) {
|
||
rb_sys_fail("sysconf(_SC_NPROCESSORS_ONLN)");
|
||
}
|
||
return LONG2NUM(ret);
|
||
}
|
||
#else
|
- « Previous
- 1
- …
- 3
- 4
- 5
- Next »