Skip to contentSkip to conversation

node affine NUMA scheduler Nod20

PATCH New Erich Focht 1 participant 1 message Aug 21, 2002

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 node affine NUMA scheduler Nod20

Hi,

here is an update of the node affine NUMA scheduler built on top of the O(1) scheduler. General information about it can be found at
http://home.arcor.de/efocht/sched

The main changes compared to the previous version are:
- modified migration_thread to allow "asynchronous" pushing of a task to another CPU from within load_balance().
- load_balance() checks for the case of a single task running on a remote node. As this task cannot be stolen by a CPU from its homenode (because a running task cannot be stolen within the O(1) scheduler framework), it will be pushed to its homenode if that one has <25% load.

These changes should solve the problem of long running tasks beeing pushed away from their homenodes during short peaks of load on the machine and not beeing able to return to their homenodes even if those are idle.

The patch at
http://home.arcor.de/efocht/sched/Nod20_2.4.18-ia64-O1ef7.patch
is for 2.4.18-IA64 and requires the O(1) patch
http://home.arcor.de/efocht/sched/O1_ia64-ef7-2.4.18.patch.bz2
These patches are well tested on IA64 platforms (16xItanium NEC Azusa, 32xItanium NEC Asama, non-NUMA Itanium).

For monitoring the runqueue loads and load balancer decisions one can apply additionally
http://home.arcor.de/efocht/sched/proc_sched_hist_2.4.18-ia64-O1ef7.patch
This creates per runqueue files in /proc/sched/load and /proc/sched/history that which let one monitor the load, the initial load balancing and the stealing decisions of the load balancer.

The attached patch is for the latest 2.5.31 bitkeeper tree. It is very experimental and pretty untested. Thanks to Michael Hohnbaum who ported the Nod18 version to 2.5.25 and helped a lot with the transition to 2.5. This patch might work on NUMA-Q... I'll try to keep the BK tree bk://numa-ef.bkbits.net/2.5-numa-sched up to date, so if someone has fixes, improvements, ports to other platforms, please send patches or changesets against that tree.

Thanks,
best regards,
Erich

Signature · 3 lines
Global warming and climate change is everyones business!
Links? http://unfccc.int/ http://www.climnet.org/
       http://www.fossil-of-the-day.org/
arch/i386/config.in +4 -0
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
@@ -166,6 +166,10 @@
       define_bool CONFIG_X86_IO_APIC y
    fi
 else
+   bool '  Enable NUMA scheduler' CONFIG_NUMA_SCHED
+   if [ "$CONFIG_NUMA_SCHED" = "y" ]; then
+      bool '  Enable node affine scheduler' CONFIG_NODE_AFFINE_SCHED
+   fi
    bool 'Multiquad NUMA system' CONFIG_MULTIQUAD
 fi
 
arch/i386/kernel/smpboot.c +18 -1
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
@@ -764,6 +764,8 @@
 
 extern unsigned long cpu_initialized;
 
+static int __initdata nr_lnodes = 0;
+
 static void __init do_boot_cpu (int apicid) 
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
@@ -772,11 +774,17 @@
 {
 	struct task_struct *idle;
 	unsigned long boot_error = 0;
-	int timeout, cpu;
+	int timeout, cpu, cell;
 	unsigned long start_eip;
 	unsigned short nmi_high, nmi_low;
 
 	cpu = ++cpucount;
+#ifdef CONFIG_NUMA_SCHED
+	cell = SAPICID_TO_PNODE(apicid);
+	if (pnode_to_lnode[cell] < 0) {
+		pnode_to_lnode[cell] = nr_lnodes++;
+	}
+#endif
 	/*
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
@@ -995,6 +1003,10 @@
 	set_bit(0, &cpu_callout_map);
 	boot_cpu_logical_apicid = logical_smp_processor_id();
 	map_cpu_to_boot_apicid(0, boot_cpu_apicid);
+#ifdef CONFIG_NUMA_SCHED
+	pnode_to_lnode[SAPICID_TO_PNODE(boot_cpu_apicid)] = nr_lnodes++;
+	printk("boot_cpu_apicid = %d, nr_lnodes = %d, lnode = %d\n", boot_cpu_apicid, nr_lnodes, pnode_to_lnode[0]);
+#endif
 
 	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
@@ -1221,4 +1233,9 @@
 void __init smp_cpus_done(unsigned int max_cpus)
 {
 	zap_low_mappings();
+#ifdef CONFIG_NUMA_SCHED
+	pooldata_lock();
+	bld_pools();
+	pooldata_unlock();
+#endif
 }
arch/ia64/config.in +8 -0
diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in
@@ -67,11 +67,19 @@
 if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ];
 then
 	bool '  Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
+   	bool '  Enable NUMA scheduler' CONFIG_NUMA_SCHED
+   	if [ "$CONFIG_NUMA_SCHED" = "y" ]; then
+      	   bool '  Enable node affine scheduler' CONFIG_NODE_AFFINE_SCHED
+   	fi
 	define_bool CONFIG_PM y
 fi
 
 if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then
 	define_bool CONFIG_IA64_SGI_SN y
+   	bool '  Enable NUMA scheduler' CONFIG_NUMA_SCHED
+   	if [ "$CONFIG_NUMA_SCHED" = "y" ]; then
+      	   bool '  Enable node affine scheduler' CONFIG_NODE_AFFINE_SCHED
+   	fi
 	bool '  Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG
 	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
 	bool '  Enable autotest (llsc). Option to run cache test instead of booting' \
arch/ia64/kernel/smpboot.c +39 -2

81 lines not on this page · raw message

fs/exec.c +5 -0
diff -Nru a/fs/exec.c b/fs/exec.c
@@ -865,6 +865,11 @@
 	int retval;
 	int i;
 
+#ifdef CONFIG_NODE_AFFINE_SCHED
+	if (current->node_policy == NODPOL_EXEC)
+		sched_balance_exec();
+#endif
+
 	file = open_exec(filename);
 
 	retval = PTR_ERR(file);
include/asm-i386/atomic.h +12 -0
diff -Nru a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
@@ -111,6 +111,18 @@
 }
 
 /**
+ * atomic_inc_return - increment atomic variable and return new value
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1 and return it's new value.  Note that
+ * the guaranteed useful range of an atomic_t is only 24 bits.
+ */
+static inline int atomic_inc_return(atomic_t *v){
+	atomic_inc(v);
+	return v->counter;
+}
+
+/**
  * atomic_dec - decrement atomic variable
  * @v: pointer of type atomic_t
  * 
include/asm-i386/smp.h +6 -0
diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h
@@ -124,5 +124,11 @@
 
 #define NO_PROC_ID		0xFF		/* No processor magic marker */
 
+#ifdef CONFIG_NUMA_SCHED
+#define NR_NODES               8
+#define cpu_physical_id(cpuid) (cpu_to_physical_apicid(cpuid))
+#define SAPICID_TO_PNODE(hwid)  (hwid >> 4)
+#endif
+
 #endif
 #endif
include/asm-ia64/smp.h +27 -0
diff -Nru a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
@@ -13,6 +13,7 @@
 
 #ifdef CONFIG_SMP
 
+#include <linux/cache.h>
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
@@ -129,6 +130,32 @@
 extern void __cpu_die (unsigned int cpu);
 extern int __cpu_up (unsigned int cpu);
 extern void __init smp_build_cpu_map(void);
+
+#ifdef CONFIG_NUMA_SCHED
+#ifdef CONFIG_IA64_DIG
+/* sooner or later this should be a configurable parameter [EF] */
+#define NR_NODES 8
+/* 
+ * This is the node ID on the NEC AzusA, 
+ * on LION and BigSur it correctly initializes to node 0
+ */
+#define SAPICID_TO_PNODE(hwid) ((hwid >> 12) & 0xff)
+
+#elif defined(CONFIG_IA64_SGI_SN)
+
+/*
+ * SGI SN1 & SN2 specific macros
+ */
+#define NR_NODES 32
+#define SAPICID_TO_PNODE(hwid) cpuid_to_cnodeid(hwid)
+
+#endif
+
+#else   /* CONFIG_NODE_AFFINE_SCHED */
+#define NR_NODES               1
+#define CPU_TO_NODE(cpu)       0
+#define SAPICID_TO_PNODE(hwid)  0
+#endif  /* CONFIG_NODE_AFFINE_SCHED */
 
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
include/linux/prctl.h +6 -0
diff -Nru a/include/linux/prctl.h b/include/linux/prctl.h
@@ -34,4 +34,10 @@
 # define PR_FP_EXC_ASYNC	2	/* async recoverable exception mode */
 # define PR_FP_EXC_PRECISE	3	/* precise exception mode */
 
+/* Get/set node for node-affine scheduling */
+#define PR_GET_NODE       16
+#define PR_SET_NODE       17
+#define PR_GET_NODPOL     18
+#define PR_SET_NODPOL     19
+
 #endif /* _LINUX_PRCTL_H */
include/linux/sched.h +56 -2

76 lines not on this page · raw message

kernel/fork.c +7 -0
diff -Nru a/kernel/fork.c b/kernel/fork.c
@@ -727,6 +727,13 @@
 #ifdef CONFIG_SMP
 	{
 		int i;
+#ifdef CONFIG_NODE_AFFINE_SCHED
+		if (p->node_policy == NODPOL_FORK_ALL ||
+		    (p->node_policy == NODPOL_FORK && !(clone_flags & CLONE_VM)))
+			{
+			sched_balance_fork(p);
+			}
+#endif
 
 		/* ?? should we just memset this ?? */
 		for(i = 0; i < NR_CPUS; i++)
kernel/ksyms.c +12 -0
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
@@ -601,6 +601,18 @@
 
 EXPORT_SYMBOL(tasklist_lock);
 EXPORT_SYMBOL(pidhash);
+
+#ifdef CONFIG_NUMA_SCHED
+#include <linux/sched.h>
+EXPORT_SYMBOL(runqueues_address);
+EXPORT_SYMBOL(numpools);
+EXPORT_SYMBOL(pool_ptr);
+EXPORT_SYMBOL(pool_cpus);
+EXPORT_SYMBOL(pool_nr_cpus);
+EXPORT_SYMBOL(pool_mask);
+EXPORT_SYMBOL(sched_migrate_task);
+#endif
+
 #if defined(CONFIG_SMP) && defined(__GENERIC_PER_CPU)
 EXPORT_SYMBOL(__per_cpu_offset);
 #endif
kernel/sched.c +637 -119

921 lines not on this page · raw message

kernel/softirq.c +1 -0
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
@@ -365,6 +365,7 @@
 	set_cpus_allowed(current, 1UL << cpu);
 	if (smp_processor_id() != cpu)
 		BUG();
+	set_task_node(current, CPU_TO_NODE(cpu));
 
 	sprintf(current->comm, "ksoftirqd_CPU%d", cpu);
 
kernel/sys.c +61 -0

73 lines not on this page · raw message