[前][次][番号順一覧][スレッド一覧]

ruby-changes:35857

From: akr <ko1@a...>
Date: Wed, 15 Oct 2014 18:41:37 +0900 (JST)
Subject: [ruby-changes:35857] akr:r47939 (trunk): * ext/etc/etc.c (etc_nprocessors_affinity): use sched_getaffinity

akr	2014-10-15 18:41:25 +0900 (Wed, 15 Oct 2014)

  New Revision: 47939

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47939

  Log:
    * 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.
    
      [Feature #10267] etc-nprocessors-kosaki2.patch

  Modified files:
    trunk/ChangeLog
    trunk/configure.in
    trunk/ext/etc/etc.c
Index: configure.in
===================================================================
--- configure.in	(revision 47938)
+++ configure.in	(revision 47939)
@@ -2052,6 +2052,7 @@ AC_CHECK_FUNCS(pread) https://github.com/ruby/ruby/blob/trunk/configure.in#L2052
 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)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 47938)
+++ ChangeLog	(revision 47939)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Oct 15 18:26:19 2014  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* 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.
+
+	  [Feature #10267] etc-nprocessors-kosaki2.patch
+
 Wed Oct 15 17:53:28 2014  Tanaka Akira  <akr@f...>
 
 	* test/ruby/envutil.rb (assert_pattern_list) Renamed from
Index: ext/etc/etc.c
===================================================================
--- ext/etc/etc.c	(revision 47938)
+++ ext/etc/etc.c	(revision 47939)
@@ -30,6 +30,10 @@ https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L30
 #include <sys/utsname.h>
 #endif
 
+#ifdef HAVE_SCHED_GETAFFINITY
+#include <sched.h>
+#endif
+
 static VALUE sPasswd;
 #ifdef HAVE_GETGRENT
 static VALUE sGroup;
@@ -904,6 +908,54 @@ io_pathconf(VALUE io, VALUE arg) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L908
 #endif
 
 #if (defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)) || defined(_WIN32)
+
+#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.
  *
@@ -912,12 +964,21 @@ io_pathconf(VALUE io, VALUE arg) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L964
  *
  * 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)
@@ -925,6 +986,17 @@ etc_nprocessors(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L986
     long ret;
 
 #if !defined(_WIN32)
+
+#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) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]