Open MPI logo

Hardware Locality Development Mailing List Archives

  |   Home   |   Support   |   FAQ   |   all Hardware Locality Development mailing list

Subject: [hwloc-devel] [PATCH 2/2] Provide hwloc_cpuset_next() and use it in hwloc_cpuset_foreach
From: Bert Wesarg (bert.wesarg_at_[hidden])
Date: 2010-03-11 20:10:01


The hwloc_cpuset_next() will calculate the next cpu behind a given one.

Use hwloc_cpuset_first() and hwloc_cpuset_next() in hwloc_cpuset_foreach()
to sparsely iterate over a cpuset.

Regards,
Bert

---
 doc/Makefile.am                        |    1 +
 include/hwloc/cpuset.h                 |    9 ++++++---
 include/hwloc/rename.h                 |    1 +
 src/cpuset.c                           |   24 ++++++++++++++++++++++++
 tests/hwloc_cpuset_first_last_weight.c |   28 +++++++++++++++++++++++++++-
 5 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 9c7bcf7..6fed82c 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -266,6 +266,7 @@ man3_MANS = \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_isset.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_iszero.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_last.3 \
+        $(DOX_MAN_DIR)/man3/hwloc_cpuset_next.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_notset.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_orset.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_set.3 \
diff --git a/include/hwloc/cpuset.h b/include/hwloc/cpuset.h
index ad2dab4..5a629e9 100644
--- a/include/hwloc/cpuset.h
+++ b/include/hwloc/cpuset.h
@@ -156,6 +156,9 @@ HWLOC_DECLSPEC int hwloc_cpuset_first(hwloc_const_cpuset_t set) __hwloc_attribut
 /** \brief Compute the last CPU (most significant bit) in CPU set \p set */
 HWLOC_DECLSPEC int hwloc_cpuset_last(hwloc_const_cpuset_t set) __hwloc_attribute_pure;
 
+/** \brief Compute the next CPU in CPU set \p set which is after CPU \p prev_cpu */
+HWLOC_DECLSPEC int hwloc_cpuset_next(hwloc_const_cpuset_t set, unsigned prev_cpu) __hwloc_attribute_pure;
+
 /** \brief Keep a single CPU among those set in CPU set \p set
  *
  * Might be used before binding so that the process does not
@@ -188,13 +191,13 @@ HWLOC_DECLSPEC int hwloc_cpuset_weight(hwloc_const_cpuset_t set) __hwloc_attribu
  */
 #define hwloc_cpuset_foreach_begin(cpu, set) \
 do { \
-        for (cpu = 0; cpu < HWLOC_NBMAXCPUS; cpu++) { \
-                if (hwloc_cpuset_isset(set, cpu)) {
+        for (cpu = hwloc_cpuset_first(set); \
+             cpu != -1; \
+             cpu = hwloc_cpuset_next(set, cpu)) { \
 /** \brief End of loop. Needs a terminating ';'.
  *
  * \sa hwloc_cpuset_foreach_begin */
 #define hwloc_cpuset_foreach_end() \
-                } \
         } \
 } while (0)
 
diff --git a/include/hwloc/rename.h b/include/hwloc/rename.h
index 6ebb454..bf1b600 100644
--- a/include/hwloc/rename.h
+++ b/include/hwloc/rename.h
@@ -165,6 +165,7 @@
 #define hwloc_cpuset_notset HWLOC_NAME(cpuset_notset)
 #define hwloc_cpuset_first HWLOC_NAME(cpuset_first)
 #define hwloc_cpuset_last HWLOC_NAME(cpuset_last)
+#define hwloc_cpuset_next HWLOC_NAME(cpuset_next)
 #define hwloc_cpuset_singlify HWLOC_NAME(cpuset_singlify)
 #define hwloc_cpuset_compare_first HWLOC_NAME(cpuset_compare_first)
 #define hwloc_cpuset_compare HWLOC_NAME(cpuset_compare)
diff --git a/src/cpuset.c b/src/cpuset.c
index 1787489..e2f9b16 100644
--- a/src/cpuset.c
+++ b/src/cpuset.c
@@ -510,6 +510,30 @@ int hwloc_cpuset_last(const struct hwloc_cpuset_s * set)
 	return -1;
 }
 
+int hwloc_cpuset_next(const struct hwloc_cpuset_s * set, unsigned prev_cpu)
+{
+	int i = HWLOC_CPUSUBSET_INDEX(prev_cpu + 1);
+
+	HWLOC__CPUSET_CHECK(set);
+
+	for(; i<HWLOC_CPUSUBSET_COUNT; i++) {
+		unsigned long w = HWLOC_CPUSUBSET_SUBSET(*set,i);
+
+		/* if the prev cpu is in the same word as the possible next one,
+		   we need to mask out previous cpus */
+		if (HWLOC_CPUSUBSET_INDEX(prev_cpu) == i) {
+			w &= ~((HWLOC_CPUSUBSET_VAL(prev_cpu) << 1) - 1);
+		}
+
+		/* subsets are unsigned longs, use ffsl */
+		int _ffs = hwloc_ffsl(w);
+		if (_ffs>0)
+			return _ffs - 1 + HWLOC_CPUSUBSET_SIZE*i;
+	}
+
+	return -1;
+}
+
 void hwloc_cpuset_singlify(struct hwloc_cpuset_s * set)
 {
 	int i,found = 0;
diff --git a/tests/hwloc_cpuset_first_last_weight.c b/tests/hwloc_cpuset_first_last_weight.c
index 093aea1..8a65d8e 100644
--- a/tests/hwloc_cpuset_first_last_weight.c
+++ b/tests/hwloc_cpuset_first_last_weight.c
@@ -8,22 +8,27 @@
 
 #include <assert.h>
 
-/* check hwloc_cpuset_first(), _last() and _weight() */
+/* check hwloc_cpuset_first(), _last(), _next() and _weight() */
 
 int main(void)
 {
   hwloc_cpuset_t set;
+  int i, cpu, expected_cpu;
 
   /* empty set */
   set = hwloc_cpuset_alloc();
   assert(hwloc_cpuset_first(set) == -1);
   assert(hwloc_cpuset_last(set) == -1);
+  assert(hwloc_cpuset_next(set, 0) == -1);
   assert(hwloc_cpuset_weight(set) == 0);
 
   /* full set */
   hwloc_cpuset_fill(set);
   assert(hwloc_cpuset_first(set) == 0);
   assert(hwloc_cpuset_last(set) == HWLOC_NBMAXCPUS-1);
+  assert(hwloc_cpuset_next(set, 0) == 1);
+  assert(hwloc_cpuset_next(set, HWLOC_NBMAXCPUS-2) == HWLOC_NBMAXCPUS-1);
+  assert(hwloc_cpuset_next(set, HWLOC_NBMAXCPUS-1) == -1);
   assert(hwloc_cpuset_weight(set) == HWLOC_NBMAXCPUS);
 
   /* custom sets */
@@ -31,16 +36,37 @@ int main(void)
   hwloc_cpuset_set_range(set, 36, 59);
   assert(hwloc_cpuset_first(set) == 36);
   assert(hwloc_cpuset_last(set) == 59);
+  assert(hwloc_cpuset_next(set, 0) == 36);
+  assert(hwloc_cpuset_next(set, 36) == 37);
+  assert(hwloc_cpuset_next(set, 59) == -1);
   assert(hwloc_cpuset_weight(set) == 24);
   hwloc_cpuset_set_range(set, 136, 259);
   assert(hwloc_cpuset_first(set) == 36);
   assert(hwloc_cpuset_last(set) == 259);
+  assert(hwloc_cpuset_next(set, 59) == 136);
+  assert(hwloc_cpuset_next(set, 259) == -1);
   assert(hwloc_cpuset_weight(set) == 148);
   hwloc_cpuset_clr(set, 199);
   assert(hwloc_cpuset_first(set) == 36);
   assert(hwloc_cpuset_last(set) == 259);
+  assert(hwloc_cpuset_next(set, 198) == 200);
+  assert(hwloc_cpuset_next(set, 199) == 200);
   assert(hwloc_cpuset_weight(set) == 147);
 
+  i = 0;
+  hwloc_cpuset_foreach_begin(cpu, set) {
+    if (0 <= i && i < 24)
+      expected_cpu = i + 36;
+    else if (24 <= i && i < 87)
+      expected_cpu = i + 112;
+    else if (87 <= i && i < 147)
+      expected_cpu = i + 113;
+
+    assert(expected_cpu == cpu);
+
+    i++;
+  } hwloc_cpuset_foreach_end();
+
   hwloc_cpuset_free(set);
 
   return 0;
-- 
tg: (1926bee..) bw/sparse-cpuset-foreach (depends on: bw/semi-colon-safe-foreach)