latest numa/base patches
Subsystems (14)
cover latest numa/base patches
This is the split-out series of mm/ patches that got no objections from the latest (v15) posting of numa/core. If everyone is still fine with these then these will be merge candidates for v3.8.
I left out the more contentious policy bits that people are still arguing about.
The numa/base tree can also be found here:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git numa/base
Thanks,
Ingo
------------------->
Andrea Arcangeli (1):
numa, mm: Support NUMA hinting page faults from gup/gup_fast
Gerald Schaefer (1):
sched, numa, mm, s390/thp: Implement pmd_pgprot() for s390
Ingo Molnar (1):
mm/pgprot: Move the pgprot_modify() fallback definition to mm.h
Lee Schermerhorn (3):
mm/mpol: Add MPOL_MF_NOOP
mm/mpol: Check for misplaced page
mm/mpol: Add MPOL_MF_LAZY
Peter Zijlstra (7):
sched, numa, mm: Make find_busiest_queue() a method sched, numa, mm: Describe the NUMA scheduling problem formally mm/thp: Preserve pgprot across huge page split mm/mpol: Make MPOL_LOCAL a real policy
mm/mpol: Create special PROT_NONE infrastructure mm/migrate: Introduce migrate_misplaced_page() mm/mpol: Use special PROT_NONE to migrate pages
Ralf Baechle (1):
sched, numa, mm, MIPS/thp: Add pmd_pgprot() implementation
Rik van Riel (5):
mm/generic: Only flush the local TLB in ptep_set_access_flags() x86/mm: Only do a local tlb flush in ptep_set_access_flags() x86/mm: Introduce pte_accessible()
mm: Only flush the TLB when clearing an accessible pte x86/mm: Completely drop the TLB flush from ptep_set_access_flags()
Documentation/scheduler/numa-problem.txt | 230 +++++++++++++++++++++++++++++++ arch/mips/include/asm/pgtable.h | 2 + arch/s390/include/asm/pgtable.h | 13 ++ arch/x86/include/asm/pgtable.h | 7 + arch/x86/mm/pgtable.c | 8 +- include/asm-generic/pgtable.h | 4 + include/linux/huge_mm.h | 19 +++ include/linux/mempolicy.h | 8 ++ include/linux/migrate.h | 7 + include/linux/migrate_mode.h | 3 + include/linux/mm.h | 32 +++++ include/uapi/linux/mempolicy.h | 16 ++- kernel/sched/fair.c | 20 +-- mm/huge_memory.c | 174 +++++++++++++++-------- mm/memory.c | 119 +++++++++++++++- mm/mempolicy.c | 143 +++++++++++++++---- mm/migrate.c | 85 ++++++++++-- mm/mprotect.c | 31 +++-- mm/pgtable-generic.c | 9 +- 19 files changed, 807 insertions(+), 123 deletions(-) create mode 100644 Documentation/scheduler/numa-problem.txt
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/19 mm/generic: Only flush the local TLB in ptep_set_access_flags()
From: Rik van Riel <[email protected]>
The function ptep_set_access_flags() is only ever used to upgrade access permissions to a page - i.e. they make it less restrictive.
That means the only negative side effect of not flushing remote TLBs in this function is that other CPUs may incur spurious page faults, if they happen to access the same address, and still have a PTE with the old permissions cached in their TLB caches.
Having another CPU maybe incur a spurious page fault is faster than always incurring the cost of a remote TLB flush, so replace the remote TLB flush with a purely local one.
This should be safe on every architecture that correctly implements flush_tlb_fix_spurious_fault() to actually invalidate the local TLB entry that caused a page fault, as well as on architectures where the hardware invalidates TLB entries that cause page faults.
In the unlikely event that you are hitting what appears to be an infinite loop of page faults, and 'git bisect' took you to this changeset, your architecture needs to implement flush_tlb_fix_spurious_fault() to actually flush the TLB entry.
--- mm/pgtable-generic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/pgtable-generic.c +3 -3
@@ -12,8 +12,8 @@#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS/* -* Only sets the access flags (dirty, accessed, and -* writable). Furthermore, we know it always gets set to a "more +* Only sets the access flags (dirty, accessed), as well as write +* permission. Furthermore, we know it always gets set to a "more * permissive" setting, which allows most architectures to optimize * this. We return whether the PTE actually changed, which in turn * instructs the caller to do things like update__mmu_cache. This
@@ -27,7 +27,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,int changed = !pte_same (*ptep, entry);if (changed) {set_pte_at (vma->vm_mm, address, ptep, entry); -flush_tlb_page (vma, address); +flush_tlb_fix_spurious_fault (vma, address); }return changed; }
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/19 x86/mm: Only do a local tlb flush in ptep_set_access_flags()
In reply to Ingo MolnarFrom: Rik van Riel <[email protected]>
Because we only ever upgrade a PTE when calling ptep_set_access_flags(), it is safe to skip flushing entries on remote TLBs.
The worst that can happen is a spurious page fault on other CPUs, which would flush that TLB entry.
Lazily letting another CPU incur a spurious page fault occasionally is (much!) cheaper than aggressively flushing everybody else's TLB.
--- arch/x86/mm/pgtable.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/mm/pgtable.c +8 -1
@@ -301,6 +301,13 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)free_page ((unsigned long )pgd); } +/* +* Used to set accessed or dirty bits in the page table entries +* on other architectures. On x86, the accessed and dirty bits +* are tracked by hardware. However, do_wp_page calls this function +* to also make the pte writeable at the same time the dirty bit is +* set. In that case we do actually need to write the PTE. +*/ int ptep_set_access_flags (struct vm_area_struct *vma,unsigned long address,pte_t *ptep,pte_t entry,int dirty)
@@ -310,7 +317,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,if (changed && dirty) { *ptep = entry;pte_update_defer (vma->vm_mm, address, ptep); -flush_tlb_page (vma, address); +__flush_tlb_one (address); }return changed;
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/19 sched, numa, mm: Make find_busiest_queue() a method
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
Its a bit awkward but it was the least painful means of modifying the queue selection. Used in a later patch to conditionally use a random queue.
--- kernel/sched/fair.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
kernel/sched/fair.c +12 -8
@@ -3063,6 +3063,9 @@ struct lb_env {unsigned int loop;unsigned int loop_break;unsigned int loop_max; + +struct rq * (*find_busiest_queue)(struct lb_env *, +struct sched_group *); };/*
@@ -4236,13 +4239,14 @@ static int load_balance(int this_cpu, struct rq *this_rq,struct cpumask *cpus =__get_cpu_var (load_balance_tmpmask);struct lb_env env = { - .sd = sd, - .dst_cpu = this_cpu, - .dst_rq = this_rq, - .dst_grpmask =sched_group_cpus (sd->groups), - .idle = idle, - .loop_break = sched_nr_migrate_break, - .cpus = cpus, + .sd = sd, + .dst_cpu = this_cpu, + .dst_rq = this_rq, + .dst_grpmask =sched_group_cpus (sd->groups), + .idle = idle, + .loop_break = sched_nr_migrate_break, + .cpus = cpus, + .find_busiest_queue = find_busiest_queue, };cpumask_copy (cpus, cpu_active_mask);
@@ -4261,7 +4265,7 @@ redo: goto out_balanced; } - busiest =find_busiest_queue (&env, group); + busiest = env.find_busiest_queue (&env, group);if (!busiest) {schedstat_inc (sd, lb_nobusyq[idle]); goto out_balanced;
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 4/19 sched, numa, mm: Describe the NUMA scheduling problem formally
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
This is probably a first: formal description of a complex high-level computing problem, within the kernel source.
Rik van Riel <[email protected]>
--- Documentation/scheduler/numa-problem.txt | 230 +++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 Documentation/scheduler/numa-problem.txt
Documentation/scheduler/numa-problem.txt new file +230 -0
@@ -0,0 +1,230 @@ + + +Effective NUMA scheduling problem statement, described formally: + + * minimize interconnect traffic + +For each task 't_i' we have memory, this memory can be spread over multiple +physical nodes, let us denote this as: 'p_i,k', the memory task 't_i' has on +node 'k' in [pages]. + +If a task shares memory with another task let us denote this as: +'s_i,k', the memory shared between tasks including 't_i' residing on node +'k'. + +Let 'M' be the distribution that governs all 'p' and 's', ie. the page placement. + +Similarly, lets define 'fp_i,k' and 'fs_i,k' resp. as the (average) usage +frequency over those memory regions [1/s] such that the product gives an +(average) bandwidth 'bp' and 'bs' in [pages/s]. + +(note: multiple tasks sharing memory naturally avoid duplicat accounting + because each task will have its own access frequency 'fs') + +(pjt: I think this frequency is more numerically consistent if you explicitly + restrict p/s above to be the working-set. (It also makes explicit the + requirement for <C0,M0> to change about a change in the working set.) + + Doing this does have the nice property that it lets you use your frequency + measurement as a weak-ordering for the benefit a task would receive when + we can't fit everything. + + e.g. task1 has working set 10mb, f=90% + task2 has working set 90mb, f=10% + + Both are using 9mb/s of bandwidth, but we'd expect a much larger benefit + from task1 being on the right node than task2. ) + +Let 'C' map every task 't_i' to a cpu 'c_i' and its corresponding node 'n_i': + + C: t_i -> {c_i, n_i} + +This gives us the total interconnect traffic between nodes 'k' and 'l', +'T_k,l', as: + + T_k,l = \Sum_i bp_i,l + bs_i,l + \Sum bp_j,k + bs_j,k where n_i == k, n_j == l + +And our goal is to obtain C0 and M0 such that: + + T_k,l(C0, M0) =< T_k,l(C, M) for all C, M where k != l + +(note: we could introduce 'nc(k,l)' as the cost function of accessing memory + on node 'l' from node 'k', this would be useful for bigger NUMA systems + + pjt: I agree nice to have, but intuition suggests diminishing returns on more + usual systems given factors like things like Haswell's enormous 35mb l3 + cache and QPI being able to do a direct fetch.) + +(note: do we need a limit on the total memory per node?) + + + * fairness + +For each task 't_i' we have a weight 'w_i' (related to nice), and each cpu +'c_n' has a compute capacity 'P_n', again, using our map 'C' we can formulate a +load 'L_n': + + L_n = 1/P_n * \Sum_i w_i for all c_i = n + +using that we can formulate a load difference between CPUs + + L_n,m = | L_n - L_m | + +Which allows us to state the fairness goal like: + + L_n,m(C0) =< L_n,m(C) for all C, n != m + +(pjt: It can also be usefully stated that, having converged at C0: + + | L_n(C0) - L_m(C0) | <= 4/3 * | G_n( U(t_i, t_j) ) - G_m( U(t_i, t_j) ) | + + Where G_n,m is the greedy partition of tasks between L_n and L_m. This is + the "worst" partition we should accept; but having it gives us a useful + bound on how much we can reasonably adjust L_n/L_m at a Pareto point to + favor T_n,m. ) + +Together they give us the complete multi-objective optimization problem: + + min_C,M [ L_n,m(C), T_k,l(C,M) ] + + + +Notes: + + - the memory bandwidth problem is very much an inter-process problem, in + particular there is no such concept as a process in the above problem. + + - the naive solution would completely prefer fairness over interconnect + traffic, the more complicated solution could pick another Pareto point using + an aggregate objective function such that we balance the loss of work + efficiency against the gain of running, we'd want to more or less suggest + there to be a fixed bound on the error from the Pareto line for any + such solution. + +References: + + http://en.wikipedia.org/wiki/Mathematical_optimization + http://en.wikipedia.org/wiki/Multi-objective_optimization + + +* warning, significant hand-waving ahead, improvements welcome * + + +Partial solutions / approximations: + + 1) have task node placement be a pure preference from the 'fairness' pov. + +This means we always prefer fairness over interconnect bandwidth. This reduces +the problem to: + + min_C,M [ T_k,l(C,M) ] + + 2a) migrate memory towards 'n_i' (the task's node). + +This creates memory movement such that 'p_i,k for k != n_i' becomes 0 -- +provided 'n_i' stays stable enough and there's sufficient memory (looks like +we might need memory limits for this). + +This does however not provide us with any 's_i' (shared) information. It does +however remove 'M' since it defines memory placement in terms of task +placement. + +XXX properties of this M vs a potential optimal + + 2b) migrate memory towards 'n_i' using 2 samples. + +This separates pages into those that will migrate and those that will not due +to the two samples not matching. We could consider the first to be of 'p_i' +(private) and the second to be of 's_i' (shared). + +This interpretation can be motivated by the previously observed property that +'p_i,k for k != n_i' should become 0 under sufficient memory, leaving only +'s_i' (shared). (here we loose the need for memory limits again, since it +becomes indistinguishable from shared). + +XXX include the statistical babble on double sampling somewhere near + +This reduces the problem further; we loose 'M' as per 2a, it further reduces +the 'T_k,l' (interconnect traffic) term to only include shared (since per the +above all private will be local): + + T_k,l = \Sum_i bs_i,l for every n_i = k, l != k + +[ more or less matches the state of sched/numa and describes its remaining + problems and assumptions. It should work well for tasks without significant + shared memory usage between tasks. ] + +Possible future directions: + +Motivated by the form of 'T_k,l', try and obtain each term of the sum, so we +can evaluate it; + + 3a) add per-task per node counters + +At fault time, count the number of pages the task faults on for each node. +This should give an approximation of 'p_i' for the local node and 's_i,k' for +all remote nodes. + +While these numbers provide pages per scan, and so have the unit [pages/s] they +don't count repeat access and thus aren't actually representable for our +bandwidth numberes. + + 3b) additional frequency term + +Additionally (or instead if it turns out we don't need the raw 'p' and 's' +numbers) we can approximate the repeat accesses by using the time since marking +the pages as indication of the access frequency. + +Let 'I' be the interval of marking pages and 'e' the elapsed time since the +last marking, then we could estimate the number of accesses 'a' as 'a = I / e'. +If we then increment the node counters using 'a' instead of 1 we might get +a better estimate of bandwidth terms. + + 3c) additional averaging; can be applied on top of either a/b. + +[ Rik argues that decaying averages on 3a might be sufficient for bandwidth since + the decaying avg includes the old accesses and therefore has a measure of repeat + accesses. + + Rik also argued that the sample frequency is too low to get accurate access + frequency measurements, I'm not entirely convinced, event at low sample + frequencies the avg elapsed time 'e' over multiple samples should still + give us a fair approximation of the avg access frequency 'a'. + + So doing both b&c has a fair chance of working and allowing us to distinguish + between important and less important memory accesses. + + Experimentation has shown no benefit from the added frequency term so far. ] + +This will give us 'bp_i' and 'bs_i,k' so that we can approximately compute +'T_k,l' Our optimization problem now reads: + + min_C [ \Sum_i bs_i,l for every n_i = k, l != k ] + +And includes only shared terms, this makes sense since all task private memory +will become local as per 2. + +This suggests that if there is significant shared memory, we should try and +move towards it. + + 4) move towards where 'most' memory is + +The simplest significance test is comparing the biggest shared 's_i,k' against +the private 'p_i'. If we have more shared than private, move towards it. + +This effectively makes us move towards where most our memory is and forms a +feed-back loop with 2. We migrate memory towards us and we migrate towards +where 'most' memory is. + +(Note: even if there were two tasks fully trashing the same shared memory, it + is very rare for there to be an 50/50 split in memory, lacking a perfect + split, the small will move towards the larger. In case of the perfect + split, we'll tie-break towards the lower node number.) + + 5) 'throttle' 4's node placement + +Since per 2b our 's_i,k' and 'p_i' require at least two scans to 'stabilize' +and show representative numbers, we should limit node-migration to not be +faster than this. + + n) poke holes in previous that require more stuff and describe it.
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 04/19] sched, numa, mm: Describe the NUMA scheduling problem formally
as per 4) move towards where "most" memory. If we have a large shared memory than private memnory. Why not we just move the process towrds the memory.. instead of the memory moving towards the node. This will i guess be less cumbersome, then moving all the shared memory
Quoted 5 lines · Ingo Molnar
+Since per 2b our 's_i,k' and '
p_i' require at least two scans to 'stabilize'Documentation/scheduler/numa-problem.txt new file +2
-0+and show representative numbers, we should limit node-migration to not be +faster than this.
Re: [PATCH 04/19] sched, numa, mm: Describe the NUMA scheduling problem formally
In reply to Ingo Molnaras per 4) move towards where "most" memory. If we have a large shared memory than private memnory. Why not we just move the process towrds the memory.. instead of the memory moving towards the node. This will i guess be less cumbersome, then moving all the shared memory
Quoted 259 lines · Ingo Molnar
From: Peter Zijlstra <[email protected]>
This is probably a first: formal description of a complex high-level computing problem, within the kernel source.
Signed-off-by Peter Zijlstra <[email protected]>Cc Linus Torvalds <[email protected]>Cc Andrew Morton <[email protected]>Cc Peter Zijlstra <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Mike Galbraith <[email protected]>Rik van Riel <[email protected]>
[ Next step: generate the kernel source from such formal descriptions and retire to a tropical island! ]Signed-off-by Ingo Molnar <[email protected]>--- Documentation/scheduler/numa-problem.txt | 230 +++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 Documentation/scheduler/numa-problem.txtDocumentation/scheduler/numa-problem.txt new file +230
-1@@ -0,0 +1,230 @@ + + +Effective NUMA scheduling problem statement, described formally: + + * minimize interconnect traffic + +For each task 't_i' we have memory, this memory can be spread over multiple +physical nodes, let us denote this as: 'p_i,k', the memory task 't_i' has on +node 'k' in [pages]. + +If a task shares memory with another task let us denote this as: +'s_i,k', the memory shared between tasks including 't_i' residing on node +'k'. + +Let 'M' be the distribution that governs all 'p' and 's', ie. the page placement. + +Similarly, lets define 'fp_i,k' and 'fs_i,k' resp. as the (average) usage +frequency over those memory regions [1/s] such that the product gives an +(average) bandwidth 'bp' and 'bs' in [pages/s]. + +(note: multiple tasks sharing memory naturally avoid duplicat accounting + because each task will have its own access frequency 'fs') + +(pjt: I think this frequency is more numerically consistent if you explicitly + restrict p/s above to be the working-set. (It also makes explicit the + requirement for <C0,M0> to change about a change in the working set.) + + Doing this does have the nice property that it lets you use your frequency + measurement as a weak-ordering for the benefit a task would receive when + we can't fit everything. + + e.g. task1 has working set 10mb, f=90% + task2 has working set 90mb, f=10% + + Both are using 9mb/s of bandwidth, but we'd expect a much larger benefit + from task1 being on the right node than task2. ) + +Let 'C' map every task 't_i' to a cpu 'c_i' and its corresponding node 'n_i': + + C: t_i -> {c_i, n_i} + +This gives us the total interconnect traffic between nodes 'k' and 'l', +'T_k,l', as: + + T_k,l = \Sum_i bp_i,l + bs_i,l + \Sum bp_j,k + bs_j,k where n_i == k, n_j == l + +And our goal is to obtain C0 and M0 such that: + + T_k,l(C0, M0) =< T_k,l(C, M) for all C, M where k != l + +(note: we could introduce 'nc(k,l)' as the cost function of accessing memory + on node 'l' from node 'k', this would be useful for bigger NUMA systems + + pjt: I agree nice to have, but intuition suggests diminishing returns on more + usual systems given factors like things like Haswell's enormous 35mb l3 + cache and QPI being able to do a direct fetch.) + +(note: do we need a limit on the total memory per node?) + + + * fairness + +For each task 't_i' we have a weight 'w_i' (related to nice), and each cpu +'c_n' has a compute capacity 'P_n', again, using our map 'C' we can formulate a +load 'L_n': + + L_n = 1/P_n * \Sum_i w_i for all c_i = n + +using that we can formulate a load difference between CPUs + + L_n,m = | L_n - L_m | + +Which allows us to state the fairness goal like: + + L_n,m(C0) =< L_n,m(C) for all C, n != m + +(pjt: It can also be usefully stated that, having converged at C0: + + | L_n(C0) - L_m(C0) | <= 4/3 * | G_n( U(t_i, t_j) ) - G_m( U(t_i, t_j) ) | + + Where G_n,m is the greedy partition of tasks between L_n and L_m. This is + the "worst" partition we should accept; but having it gives us a useful + bound on how much we can reasonably adjust L_n/L_m at a Pareto point to + favor T_n,m. ) + +Together they give us the complete multi-objective optimization problem: + + min_C,M [ L_n,m(C), T_k,l(C,M) ] + + + +Notes: + + - the memory bandwidth problem is very much an inter-process problem, in + particular there is no such concept as a process in the above problem. + + - the naive solution would completely prefer fairness over interconnect + traffic, the more complicated solution could pick another Pareto point using + an aggregate objective function such that we balance the loss of work + efficiency against the gain of running, we'd want to more or less suggest + there to be a fixed bound on the error from the Pareto line for any + such solution. + +References: + + http://en.wikipedia.org/wiki/Mathematical_optimization + http://en.wikipedia.org/wiki/Multi-objective_optimization + + +* warning, significant hand-waving ahead, improvements welcome * + + +Partial solutions / approximations: + + 1) have task node placement be a pure preference from the 'fairness' pov. + +This means we always prefer fairness over interconnect bandwidth. This reduces +the problem to: + + min_C,M [ T_k,l(C,M) ] + + 2a) migrate memory towards 'n_i' (the task's node). + +This creates memory movement such that 'p_i,k for k != n_i' becomes 0 -- +provided 'n_i' stays stable enough and there's sufficient memory (looks like +we might need memory limits for this). + +This does however not provide us with any 's_i' (shared) information. It does +however remove 'M' since it defines memory placement in terms of task +placement. + +XXX properties of this M vs a potential optimal + + 2b) migrate memory towards 'n_i' using 2 samples. + +This separates pages into those that will migrate and those that will not due +to the two samples not matching. We could consider the first to be of 'p_i' +(private) and the second to be of 's_i' (shared). + +This interpretation can be motivated by the previously observed property that +'p_i,k for k != n_i' should become 0 under sufficient memory, leaving only +'s_i' (shared). (here we loose the need for memory limits again, since it +becomes indistinguishable from shared). + +XXX include the statistical babble on double sampling somewhere near + +This reduces the problem further; we loose 'M' as per 2a, it further reduces +the 'T_k,l' (interconnect traffic) term to only include shared (since per the +above all private will be local): + + T_k,l = \Sum_i bs_i,l for every n_i = k, l != k + +[ more or less matches the state of sched/numa and describes its remaining + problems and assumptions. It should work well for tasks without significant + shared memory usage between tasks. ] + +Possible future directions: + +Motivated by the form of 'T_k,l', try and obtain each term of the sum, so we +can evaluate it; + + 3a) add per-task per node counters + +At fault time, count the number of pages the task faults on for each node. +This should give an approximation of 'p_i' for the local node and 's_i,k' for +all remote nodes. + +While these numbers provide pages per scan, and so have the unit [pages/s] they +don't count repeat access and thus aren't actually representable for our +bandwidth numberes. + + 3b) additional frequency term + +Additionally (or instead if it turns out we don't need the raw 'p' and 's' +numbers) we can approximate the repeat accesses by using the time since marking +the pages as indication of the access frequency. + +Let 'I' be the interval of marking pages and 'e' the elapsed time since the +last marking, then we could estimate the number of accesses 'a' as 'a = I / e'. +If we then increment the node counters using 'a' instead of 1 we might get +a better estimate of bandwidth terms. + + 3c) additional averaging; can be applied on top of either a/b. + +[ Rik argues that decaying averages on 3a might be sufficient for bandwidth since + the decaying avg includes the old accesses and therefore has a measure of repeat + accesses. + + Rik also argued that the sample frequency is too low to get accurate access + frequency measurements, I'm not entirely convinced, event at low sample + frequencies the avg elapsed time 'e' over multiple samples should still + give us a fair approximation of the avg access frequency 'a'. + + So doing both b&c has a fair chance of working and allowing us to distinguish + between important and less important memory accesses. + + Experimentation has shown no benefit from the added frequency term so far. ] + +This will give us 'bp_i' and 'bs_i,k' so that we can approximately compute +'T_k,l' Our optimization problem now reads: + + min_C [ \Sum_i bs_i,l for every n_i = k, l != k ] + +And includes only shared terms, this makes sense since all task private memory +will become local as per 2. + +This suggests that if there is significant shared memory, we should try and +move towards it. + + 4) move towards where 'most' memory is + +The simplest significance test is comparing the biggest shared 's_i,k' against +the private 'p_i'. If we have more shared than private, move towards it. + +This effectively makes us move towards where most our memory is and forms a +feed-back loop with 2. We migrate memory towards us and we migrate towards +where 'most' memory is. + +(Note: even if there were two tasks fully trashing the same shared memory, it + is very rare for there to be an 50/50 split in memory, lacking a perfect + split, the small will move towards the larger. In case of the perfect + split, we'll tie-break towards the lower node number.) + + 5) 'throttle' 4's node placement + +Since per 2b our 's_i,k' and 'p_i' require at least two scans to 'stabilize' +and show representative numbers, we should limit node-migration to not be +faster than this. + + n) poke holes in previous that require more stuff and describe it. --1.7.11.7
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 5/19 sched, numa, mm, s390/thp: Implement pmd_pgprot() for s390
In reply to Ingo MolnarFrom: Gerald Schaefer <[email protected]>
This patch adds an implementation of pmd_pgprot() for s390, in preparation to future THP changes.
--- arch/s390/include/asm/pgtable.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
arch/s390/include/asm/pgtable.h +13 -0
@@ -1240,6 +1240,19 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, *pmdp = entry; } +static inline pgprot_t pmd_pgprot (pmd_t pmd) +{ +pgprot_t prot =PAGE_RW ; + +if (pmd_val (pmd) & _SEGMENT_ENTRY_RO) { +if (pmd_val (pmd) & _SEGMENT_ENTRY_INV) + prot =PAGE_NONE ; +else + prot =PAGE_RO ; + } +return prot; +} +static inline unsigned long massage_pgprot_pmd (pgprot_t pgprot) {unsigned long pgprot_pmd =0 ;
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 6/19 mm/thp: Preserve pgprot across huge page split
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
We're going to play games with page-protections, ensure we don't lose them over a THP split.
Collapse seems to always allocate a new (huge) page which should already end up on the new target node so loosing protections there isn't a problem.
--- arch/x86/include/asm/pgtable.h | 1 + mm/huge_memory.c | 103 ++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 54 deletions(-)
arch/x86/include/asm/pgtable.h +1 -0
@@ -349,6 +349,7 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) }#define pte_pgprot (x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK) +#define pmd_pgprot (x) __pgprot(pmd_val(x) & ~_HPAGE_CHG_MASK)#define canon_pgprot (p) __pgprot(massage_pgprot(p))
mm/huge_memory.c +49 -54
122 lines not on this page · raw message
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/19 x86/mm: Introduce pte_accessible()
In reply to Ingo MolnarFrom: Rik van Riel <[email protected]>
We need pte_present to return true for _PAGE_PROTNONE pages, to indicate that the pte is associated with a page.
However, for TLB flushing purposes, we would like to know whether the pte points to an actually accessible page. This allows us to skip remote TLB flushes for pages that are not actually accessible.
Fill in this method for x86 and provide a safe (but slower) method on other architectures.
--- arch/x86/include/asm/pgtable.h | 6 ++++++ include/asm-generic/pgtable.h | 4 ++++ 2 files changed, 10 insertions(+)
arch/x86/include/asm/pgtable.h +6 -0
@@ -408,6 +408,12 @@ static inline int pte_present(pte_t a)return pte_flags (a) & (_PAGE_PRESENT | _PAGE_PROTNONE); } +#define pte_accessible pte_accessible +static inline int pte_accessible (pte_t a) +{ +return pte_flags (a) & _PAGE_PRESENT; +} +static inline int pte_hidden (pte_t pte) {return pte_flags (pte) & _PAGE_HIDDEN;
include/asm-generic/pgtable.h +4 -0
@@ -219,6 +219,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)#define move_pte (pte, prot, old_addr, new_addr) (pte)#endif +#ifndef pte_accessible +# define pte_accessible (pte) ((void)(pte),1) +#endif +#ifndef flush_tlb_fix_spurious_fault#define flush_tlb_fix_spurious_fault (vma, address) flush_tlb_page(vma, address)#endif
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 8/19 mm: Only flush the TLB when clearing an accessible pte
In reply to Ingo MolnarFrom: Rik van Riel <[email protected]>
If ptep_clear_flush() is called to clear a page table entry that is accessible anyway by the CPU, eg. a _PAGE_PROTNONE page table entry, there is no need to flush the TLB on remote CPUs.
--- mm/pgtable-generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
mm/pgtable-generic.c +2 -1
@@ -88,7 +88,8 @@ pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address, {pte_t pte; pte =ptep_get_and_clear ((vma)->vm_mm, address, ptep); -flush_tlb_page (vma, address); +if (pte_accessible (pte)) +flush_tlb_page (vma, address);return pte; }#endif
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 9/19 sched, numa, mm, MIPS/thp: Add pmd_pgprot() implementation
In reply to Ingo MolnarFrom: Ralf Baechle <[email protected]>
Add the pmd_pgprot() method that will be needed
by the new NUMA code.
--- arch/mips/include/asm/pgtable.h | 2 ++ 1 file changed, 2 insertions(+)
arch/mips/include/asm/pgtable.h +2 -0
@@ -89,6 +89,8 @@ static inline int is_zero_pfn(unsigned long pfn)extern void paging_init (void ); +#define pmd_pgprot (x) __pgprot(pmd_val(x) & ~_PAGE_CHG_MASK) +/* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to.
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 10/19 mm/pgprot: Move the pgprot_modify() fallback definition to mm.h
In reply to Ingo Molnarpgprot_modify() is available on x86, but on other architectures it only gets defined in mm/mprotect.c - breaking the build if anything outside of mprotect.c tries to make use of this function.
Move it to the generic pgprot area in mm.h, so that an upcoming patch can make use of it.
--- include/linux/mm.h | 13 +++++++++++++ mm/mprotect.c | 7 ------- 2 files changed, 13 insertions(+), 7 deletions(-)
include/linux/mm.h +13 -0
@@ -164,6 +164,19 @@ extern pgprot_t protection_map[16];#define FAULT_FLAG_TRIED 0x40/* second try */ /* +* Some architectures (such as x86) may need to preserve certain pgprot +* bits, without complicating generic pgprot code. +* +* Most architectures don't care: +*/ +#ifndef pgprot_modify +static inline pgprot_t pgprot_modify (pgprot_t oldprot,pgprot_t newprot) +{ +return newprot; +} +#endif + +/* * vm_fault is filled by the the pagefault handler and passed to the vma's * ->fault function. The vma's ->fault is responsible for returning a bitmask * of VM_FAULT_xxx flags that give details about how the fault was handled.
mm/mprotect.c +0 -7
@@ -28,13 +28,6 @@#include <asm/cacheflush.h> #include <asm/tlbflush.h> -#ifndef pgprot_modify -static inline pgprot_t pgprot_modify (pgprot_t oldprot,pgprot_t newprot) -{ -return newprot; -} -#endif -static void change_pte_range (struct mm_struct *mm,pmd_t *pmd,unsigned long addr,unsigned long end,pgprot_t newprot,int dirty_accountable)
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 11/19 mm/mpol: Make MPOL_LOCAL a real policy
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
Make MPOL_LOCAL a real and exposed policy such that applications that relied on the previous default behaviour can explicitly request it.
--- include/uapi/linux/mempolicy.h | 1 + mm/mempolicy.c | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-)
include/uapi/linux/mempolicy.h +1 -0
@@ -20,6 +20,7 @@ enum {MPOL_PREFERRED ,MPOL_BIND ,MPOL_INTERLEAVE , +MPOL_LOCAL , MPOL_MAX, /* always last member of enum */ };
mm/mempolicy.c +6 -3
@@ -269,6 +269,10 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags, (flags & MPOL_F_RELATIVE_NODES)))return ERR_PTR (-EINVAL ); } + }else if (mode ==MPOL_LOCAL ) { +if (!nodes_empty (*nodes)) +return ERR_PTR (-EINVAL ); + mode =MPOL_PREFERRED ; }else if (nodes_empty (*nodes))return ERR_PTR (-EINVAL ); policy =kmem_cache_alloc (policy_cache,GFP_KERNEL );
@@ -2397,7 +2401,6 @@ void numa_default_policy(void)* "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag * Used only for mpol_parse_str() and mpol_to_str() */ -#define MPOL_LOCAL MPOL_MAXstatic const char *const policy_modes[] = { [MPOL_DEFAULT ] ="default" ,
@@ -2450,12 +2453,12 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)if (flags) *flags++ ='\0' ;/* terminate mode string */ -for (mode =0 ; mode <=MPOL_LOCAL ; mode++) { +for (mode =0 ; mode <MPOL_MAX ; mode++) {if (!strcmp (str, policy_modes[mode])) {break ; } } -if (mode >MPOL_LOCAL ) +if (mode >=MPOL_MAX ) goto out;switch (mode) {
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 12/19 mm/mpol: Add MPOL_MF_NOOP
In reply to Ingo MolnarFrom: Lee Schermerhorn <[email protected]>
This patch augments the MPOL_MF_LAZY feature by adding a "NOOP" policy to mbind(). When the NOOP policy is used with the 'MOVE and 'LAZY flags, mbind() will map the pages PROT_NONE so that they will be migrated on the next touch.
This allows an application to prepare for a new phase of operation where different regions of shared storage will be assigned to worker threads, w/o changing policy. Note that we could just use "default" policy in this case. However, this also allows an application to request that pages be migrated, only if necessary, to follow any arbitrary policy that might currently apply to a range of pages, without knowing the policy, or without specifying multiple mbind()s for ranges with different policies.
[ Bug in early version of mpol_parse_str() reported by Fengguang Wu. ]
--- include/uapi/linux/mempolicy.h | 1 + mm/mempolicy.c | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-)
include/uapi/linux/mempolicy.h +1 -0
@@ -21,6 +21,7 @@ enum {MPOL_BIND ,MPOL_INTERLEAVE ,MPOL_LOCAL , +MPOL_NOOP ,/* retain existing policy for range */ MPOL_MAX, /* always last member of enum */ };
mm/mempolicy.c +6 -5
@@ -251,10 +251,10 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,pr_debug ("setting mode %d flags %d nodes[0] %lx\n" , mode, flags, nodes ?nodes_addr (*nodes)[0 ] :-1 ); -if (mode ==MPOL_DEFAULT ) { +if (mode ==MPOL_DEFAULT || mode ==MPOL_NOOP ) {if (nodes && !nodes_empty (*nodes))return ERR_PTR (-EINVAL ); -return NULL ;/* simply delete any existing policy */ +return NULL ; }VM_BUG_ON (!nodes);
@@ -1146,7 +1146,7 @@ static long do_mbind(unsigned long start, unsigned long len,if (start & ~PAGE_MASK )return -EINVAL ; -if (mode ==MPOL_DEFAULT ) +if (mode ==MPOL_DEFAULT || mode ==MPOL_NOOP ) flags &= ~MPOL_MF_STRICT ; len = (len +PAGE_SIZE -1 ) &PAGE_MASK ;
@@ -2407,7 +2407,8 @@ static const char * const policy_modes[] = [MPOL_PREFERRED] = "prefer", [MPOL_BIND] = "bind", [MPOL_INTERLEAVE] = "interleave", - [MPOL_LOCAL] = "local" + [MPOL_LOCAL] = "local", + [MPOL_NOOP] = "noop", /* should not actually be used */ };
@@ -2458,7 +2459,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)break ; } } -if (mode >=MPOL_MAX ) +if (mode >=MPOL_MAX || mode ==MPOL_NOOP ) goto out;switch (mode) {
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 13/19 mm/mpol: Check for misplaced page
In reply to Ingo MolnarFrom: Lee Schermerhorn <[email protected]>
This patch provides a new function to test whether a page resides on a node that is appropriate for the mempolicy for the vma and address where the page is supposed to be mapped. This involves looking up the node where the page belongs. So, the function returns that node so that it may be used to allocated the page without consulting the policy again.
A subsequent patch will call this function from the fault path. Because of this, I don't want to go ahead and allocate the page, e.g., via alloc_page_vma() only to have to free it if it has the correct policy. So, I just mimic the alloc_page_vma() node computation logic--sort of.
Note: we could use this function to implement a MPOL_MF_STRICT behavior when migrating pages to match mbind() mempolicy--e.g., to ensure that pages in an interleaved range are reinterleaved rather than left where they are when they reside on any page in the interleave nodemask.
[ Added MPOL_F_LAZY to trigger migrate-on-fault;
simplified code now that we don't have to bother with special crap for interleaved ]
--- include/linux/mempolicy.h | 8 +++++ include/uapi/linux/mempolicy.h | 1 + mm/mempolicy.c | 76 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+)
include/linux/mempolicy.h +8 -0
@@ -198,6 +198,8 @@ static inline int vma_migratable(struct vm_area_struct *vma) return 1; } +extern int mpol_misplaced (struct page *,struct vm_area_struct *,unsigned long ); +#else struct mempolicy {};
@@ -323,5 +325,11 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,return 0 ; } +static inline int mpol_misplaced (struct page *page,struct vm_area_struct *vma, +unsigned long address) +{ +return -1 ;/* no node preference */ +} +#endif /* CONFIG_NUMA */ #endif
include/uapi/linux/mempolicy.h +1 -0
@@ -61,6 +61,7 @@ enum mpol_rebind_step {#define MPOL_F_SHARED (1 << 0)/* identify shared policies */ #define MPOL_F_LOCAL (1 << 1)/* preferred local allocation */ #define MPOL_F_REBINDING (1 << 2)/* identify policies in rebinding */ +#define MPOL_F_MOF (1 << 3)/* this policy wants migrate on fault */ #endif /* _UAPI_LINUX_MEMPOLICY_H */
mm/mempolicy.c +76 -0
82 lines not on this page · raw message
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 14/19 mm/mpol: Create special PROT_NONE infrastructure
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
In order to facilitate a lazy -- fault driven -- migration of pages, create a special transient PROT_NONE variant, we can then use the 'spurious' protection faults to drive our migrations from.
Pages that already had an effective PROT_NONE mapping will not be detected to generate these 'spuriuos' faults for the simple reason that we cannot distinguish them on their protection bits, see pte_numa().
This isn't a problem since PROT_NONE (and possible PROT_WRITE with dirty tracking) aren't used or are rare enough for us to not care about their placement.
--- include/linux/huge_mm.h | 19 +++++++++++++ include/linux/mm.h | 18 ++++++++++++ mm/huge_memory.c | 32 +++++++++++++++++++++ mm/memory.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----- mm/mprotect.c | 24 +++++++++++----- 5 files changed, 154 insertions(+), 14 deletions(-)
include/linux/huge_mm.h +19 -0
@@ -159,6 +159,13 @@ static inline struct page *compound_trans_head(struct page *page) }return page; } + +extern bool pmd_numa (struct vm_area_struct *vma,pmd_t pmd); + +extern void do_huge_pmd_numa_page (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long address,pmd_t *pmd, +unsigned int flags,pmd_t orig_pmd); +#else /* CONFIG_TRANSPARENT_HUGEPAGE */ #define HPAGE_PMD_SHIFT ({ BUILD_BUG(); 0; })#define HPAGE_PMD_MASK ({ BUILD_BUG(); 0; })
@@ -195,6 +202,18 @@ static inline int pmd_trans_huge_lock(pmd_t *pmd, {return 0 ; } + +static inline bool pmd_numa (struct vm_area_struct *vma,pmd_t pmd) +{ +return false; +} + +static inline void do_huge_pmd_numa_page (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long address,pmd_t *pmd, +unsigned int flags,pmd_t orig_pmd) +{ +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif /* _LINUX_HUGE_MM_H */
include/linux/mm.h +18 -0
@@ -1091,6 +1091,9 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,extern unsigned long do_mremap (unsigned long addr,unsigned long old_len,unsigned long new_len,unsigned long flags,unsigned long new_addr); +extern void change_protection (struct vm_area_struct *vma,unsigned long start, +unsigned long end,pgprot_t newprot, +int dirty_accountable);extern int mprotect_fixup (struct vm_area_struct *vma,struct vm_area_struct **pprev,unsigned long start,unsigned long end,unsigned long newflags);
@@ -1561,6 +1564,21 @@ static inline pgprot_t vm_get_page_prot(unsigned long vm_flags) }#endif +static inline pgprot_t vma_prot_none (struct vm_area_struct *vma) +{ +/* +* obtain PROT_NONE by removing READ|WRITE|EXEC privs +*/ +vm_flags_t vmflags = vma->vm_flags & ~(VM_READ |VM_WRITE |VM_EXEC ); +return pgprot_modify (vma->vm_page_prot,vm_get_page_prot (vmflags)); +} + +static inline void +change_prot_none (struct vm_area_struct *vma,unsigned long start,unsigned long end) +{ +change_protection (vma, start, end,vma_prot_none (vma),0 ); +} +struct vm_area_struct *find_extend_vma (struct mm_struct *,unsigned long addr);int remap_pfn_range (struct vm_area_struct *,unsigned long addr,unsigned long pfn,unsigned long size,pgprot_t );
mm/huge_memory.c +32 -0
@@ -725,6 +725,38 @@ out:return handle_pte_fault (mm, vma, address, pte, pmd, flags); } +bool pmd_numa (struct vm_area_struct *vma,pmd_t pmd) +{ +/* +* See pte_numa(). +*/ +if (pmd_same (pmd,pmd_modify (pmd, vma->vm_page_prot))) +return false; + +return pmd_same (pmd,pmd_modify (pmd,vma_prot_none (vma))); +} + +void do_huge_pmd_numa_page (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long address,pmd_t *pmd, +unsigned int flags,pmd_t entry) +{ +unsigned long haddr = address &HPAGE_PMD_MASK ; + +spin_lock (&mm->page_table_lock); +if (unlikely (!pmd_same (*pmd, entry))) + goto out_unlock; + +/* do fancy stuff */ + +/* change back to regular protection */ + entry =pmd_modify (entry, vma->vm_page_prot); +if (pmdp_set_access_flags (vma, haddr, pmd, entry,1 )) +update_mmu_cache_pmd (vma, address, entry); + +out_unlock: +spin_unlock (&mm->page_table_lock); +} +int copy_huge_pmd (struct mm_struct *dst_mm,struct mm_struct *src_mm,pmd_t *dst_pmd,pmd_t *src_pmd,unsigned long addr,struct vm_area_struct *vma)
mm/memory.c +68 -7
111 lines not on this page · raw message
mm/mprotect.c +17 -7
@@ -112,7 +112,7 @@ static inline void change_pud_range(struct vm_area_struct *vma, pgd_t *pgd, }while (pud++, addr = next, addr != end); } -static void change_protection (struct vm_area_struct *vma, +static void change_protection_range (struct vm_area_struct *vma,unsigned long addr,unsigned long end,pgprot_t newprot,int dirty_accountable) {
@@ -134,6 +134,20 @@ static void change_protection(struct vm_area_struct *vma,flush_tlb_range (vma, start, end); } +void change_protection (struct vm_area_struct *vma,unsigned long start, +unsigned long end,pgprot_t newprot, +int dirty_accountable) +{ +struct mm_struct *mm = vma->vm_mm; + +mmu_notifier_invalidate_range_start (mm, start, end); +if (is_vm_hugetlb_page (vma)) +hugetlb_change_protection (vma, start, end, newprot); +else +change_protection_range (vma, start, end, newprot, dirty_accountable); +mmu_notifier_invalidate_range_end (mm, start, end); +} +int mprotect_fixup (struct vm_area_struct *vma,struct vm_area_struct **pprev,unsigned long start,unsigned long end,unsigned long newflags)
@@ -206,12 +220,8 @@ success: dirty_accountable =1 ; } -mmu_notifier_invalidate_range_start (mm, start, end); -if (is_vm_hugetlb_page (vma)) -hugetlb_change_protection (vma, start, end, vma->vm_page_prot); -else -change_protection (vma, start, end, vma->vm_page_prot, dirty_accountable); -mmu_notifier_invalidate_range_end (mm, start, end); +change_protection (vma, start, end, vma->vm_page_prot, dirty_accountable); +vm_stat_account (mm, oldflags, vma->vm_file, -nrpages);vm_stat_account (mm, newflags, vma->vm_file, nrpages);perf_event_mmap (vma);
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 15/19 mm/mpol: Add MPOL_MF_LAZY
In reply to Ingo MolnarFrom: Lee Schermerhorn <[email protected]>
This patch adds another mbind() flag to request "lazy migration". The flag, MPOL_MF_LAZY, modifies MPOL_MF_MOVE* such that the selected pages are marked PROT_NONE. The pages will be migrated in the fault path on "first touch", if the policy dictates at that time.
"Lazy Migration" will allow testing of migrate-on-fault via mbind(). Also allows applications to specify that only subsequently touched pages be migrated to obey new policy, instead of all pages in range. This can be useful for multi-threaded applications working on a large shared data area that is initialized by an initial thread resulting in all pages on one [or a few, if overflowed] nodes. After PROT_NONE, the pages in regions assigned to the worker threads will be automatically migrated local to the threads on 1st touch.
--- include/uapi/linux/mempolicy.h | 13 ++++++++--- mm/mempolicy.c | 49 +++++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 20 deletions(-)
include/uapi/linux/mempolicy.h +10 -3
@@ -49,9 +49,16 @@ enum mpol_rebind_step {/* Flags for mbind */ #define MPOL_MF_STRICT (1<<0)/* Verify existing pages in the mapping */ -#define MPOL_MF_MOVE (1<<1)/* Move pages owned by this process to conform to mapping */ -#define MPOL_MF_MOVE_ALL (1<<2)/* Move every page to conform to mapping */ -#define MPOL_MF_INTERNAL (1<<3)/* Internal flags start here */ +#define MPOL_MF_MOVE (1<<1)/* Move pages owned by this process to conform +to policy */ +#define MPOL_MF_MOVE_ALL (1<<2)/* Move every page to conform to policy */ +#define MPOL_MF_LAZY (1<<3)/* Modifies '_MOVE: lazy migrate on fault */ +#define MPOL_MF_INTERNAL (1<<4)/* Internal flags start here */ + +#define MPOL_MF_VALID (MPOL_MF_STRICT | \ + MPOL_MF_MOVE | \ + MPOL_MF_MOVE_ALL | \ + MPOL_MF_LAZY)/* * Internal flags that share the struct mempolicy flags word with
mm/mempolicy.c +32 -17
95 lines not on this page · raw message
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 16/19 numa, mm: Support NUMA hinting page faults from gup/gup_fast
In reply to Ingo MolnarFrom: Andrea Arcangeli <[email protected]>
Introduce FOLL_NUMA to tell follow_page to check pte/pmd_numa. get_user_pages must use FOLL_NUMA, and it's safe to do so because it always invokes handle_mm_fault and retries the follow_page later.
KVM secondary MMU page faults will trigger the NUMA hinting page faults through gup_fast -> get_user_pages -> follow_page -> handle_mm_fault.
Other follow_page callers like KSM should not use FOLL_NUMA, or they would fail to get the pages if they use follow_page instead of get_user_pages.
[ This patch was picked up from the AutoNUMA tree. ]
--- include/linux/mm.h | 1 + mm/memory.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+)
include/linux/mm.h +1 -0
@@ -1600,6 +1600,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,#define FOLL_MLOCK 0x40/* mark page as mlocked */ #define FOLL_SPLIT 0x80/* don't return transhuge pages, split them */ #define FOLL_HWPOISON 0x100/* check page is hwpoisoned */ +#define FOLL_NUMA 0x200/* force NUMA hinting page fault */ typedef int (*pte_fn_t )(pte_t *pte,pgtable_t token,unsigned long addr,void *data);
mm/memory.c +17 -0
@@ -1536,6 +1536,8 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, page =follow_huge_pmd (mm, address, pmd, flags &FOLL_WRITE ); goto out; } +if ((flags &FOLL_NUMA ) &&pmd_numa (vma, *pmd)) + goto no_page_table;if (pmd_trans_huge (*pmd)) {if (flags &FOLL_SPLIT ) {split_huge_page_pmd (mm, pmd);
@@ -1565,6 +1567,8 @@ split_fallthrough: pte = *ptep;if (!pte_present (pte)) goto no_page; +if ((flags &FOLL_NUMA ) &&pte_numa (vma, pte)) + goto no_page;if ((flags &FOLL_WRITE ) && !pte_write (pte)) goto unlock;
@@ -1716,6 +1720,19 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); vm_flags &= (gup_flags &FOLL_FORCE ) ? (VM_MAYREAD |VM_MAYWRITE ) : (VM_READ |VM_WRITE ); + +/* +* If FOLL_FORCE and FOLL_NUMA are both set, handle_mm_fault +* would be called on PROT_NONE ranges. We must never invoke +* handle_mm_fault on PROT_NONE ranges or the NUMA hinting +* page faults would unprotect the PROT_NONE ranges if +* _PAGE_NUMA and _PAGE_PROTNONE are sharing the same pte/pmd +* bitflag. So to avoid that, don't set FOLL_NUMA if +* FOLL_FORCE is set. +*/ +if (!(gup_flags &FOLL_FORCE )) + gup_flags |=FOLL_NUMA ; + i =0 ; do {
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 17/19 mm/migrate: Introduce migrate_misplaced_page()
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
Add migrate_misplaced_page() which deals with migrating pages from faults.
This includes adding a new MIGRATE_FAULT migration mode to deal with the extra page reference required due to having to look up the page.
--- include/linux/migrate.h | 7 ++++ include/linux/migrate_mode.h | 3 ++ mm/migrate.c | 85 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 87 insertions(+), 8 deletions(-)
include/linux/migrate.h +7 -0
@@ -30,6 +30,7 @@ extern int migrate_vmas(struct mm_struct *mm,extern void migrate_page_copy (struct page *newpage,struct page *page);extern int migrate_huge_page_move_mapping (struct address_space *mapping,struct page *newpage,struct page *page); +extern int migrate_misplaced_page (struct page *page,int node);#else static inline void putback_lru_pages (struct list_head *l) {}
@@ -63,5 +64,11 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,#define migrate_page NULL#define fail_migrate_page NULL +static inline +int migrate_misplaced_page (struct page *page,int node) +{ +return -EAGAIN ;/* can't migrate now */ +}#endif /* CONFIG_MIGRATION */ +#endif /* _LINUX_MIGRATE_H */
include/linux/migrate_mode.h +3 -0
@@ -6,11 +6,14 @@* on most operations but not ->writepage as the potential stall time * is too significant * MIGRATE_SYNC will block when migrating pages +* MIGRATE_FAULT called from the fault path to migrate-on-fault for mempolicy +* this path has an extra reference count */ enum migrate_mode {MIGRATE_ASYNC ,MIGRATE_SYNC_LIGHT ,MIGRATE_SYNC , +MIGRATE_FAULT , };#endif /* MIGRATE_MODE_H_INCLUDED */
mm/migrate.c +77 -8
128 lines not on this page · raw message
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 17/19 mm/migrate: Introduce migrate_misplaced_page()
Quoted 8 lines · Ingo Molnar
From: Peter Zijlstra <[email protected]>
Add
migrate_misplaced_page()which deals with migrating pages from faults.This includes adding a new
MIGRATE_FAULTmigration mode to deal with the extra page reference required due to having to look up the page.
[...]
include/linux/migrate_mode.h line 11
Quoted 9 lines
include/linux/migrate_mode.h +2
-0@@ -6,11 +6,14 @@* on most operations but not ->writepage as the potential stall time * is too significant * MIGRATE_SYNC will block when migrating pages +* MIGRATE_FAULT called from the fault path to migrate-on-fault for mempolicy +* this path has an extra reference count */
Note, this is still the older, open-coded version.
The newer replacement version created from Mel's patch which reuses migrate_pages() and is nicer on out-of-node-memory conditions and is cleaner all around can be found below.
I tested it today and it appears to work fine. I noticed no performance improvement or performance drop from it - if it holds up in testing it will be part of the -v17 release of numa/core.
Thanks,
Ingo
-------------------------->
Subject: mm/migration: Introduce migrate_misplaced_page()
From: Mel Gorman <[email protected]>
Date: Fri, 16 Nov 2012 11:22:23 +0000
Note: This was originally based on Peter's patch "mm/migrate: Introduce
migrate_misplaced_page()" but borrows extremely heavily from Andrea's "autonuma: memory follows CPU algorithm and task/mm_autonuma stats collection". The end result is barely recognisable so signed-offs had to be dropped. If original authors are ok with it, I'll re-add the signed-off-bys.
Add migrate_misplaced_page() which deals with migrating pages from faults.
--- mm/memory.c | 13 ++----- mm/migrate.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 10 deletions(-)
mm/memory.c +5 -8
@@ -3494,28 +3494,25 @@ out_pte_upgrade_unlock: out_unlock:pte_unmap_unlock (ptep, ptl); -out: +if (page) {task_numa_fault (page_nid, last_cpu,1 );put_page (page); } - +out:return 0 ; migrate:pte_unmap_unlock (ptep, ptl); -if (!migrate_misplaced_page (page, node)) { - page_nid = node; +if (migrate_misplaced_page (page, node)) { goto out; } + page =NULL ; ptep =pte_offset_map_lock (mm, pmd, address, &ptl); -if (!pte_same (*ptep, entry)) { -put_page (page); - page =NULL ; +if (!pte_same (*ptep, entry)) goto out_unlock; - } goto out_pte_upgrade_unlock; }
mm/migrate.c +101 -2
112 lines not on this page · raw message
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 17/19, v2] mm/migrate: Introduce migrate_misplaced_page()
Quoted 25 lines · Ingo Molnar
Quoted 8 lines · Ingo Molnar
From: Peter Zijlstra <[email protected]>
Add
migrate_misplaced_page()which deals with migrating pages from faults.This includes adding a new
MIGRATE_FAULTmigration mode to deal with the extra page reference required due to having to look up the page.[...]
include/linux/migrate_mode.h line 11
Quoted 9 lines
include/linux/migrate_mode.h +2
-0@@ -6,11 +6,14 @@* on most operations but not ->writepage as the potential stall time * is too significant * MIGRATE_SYNC will block when migrating pages +* MIGRATE_FAULT called from the fault path to migrate-on-fault for mempolicy +* this path has an extra reference count */ Note, this is still the older, open-coded version.
Quoted 8 lines
The newer replacement version created from Mel's patch which reuses
migrate_pages()and is nicer on out-of-node-memory conditions and is cleaner all around can be found below.I tested it today and it appears to work fine. I noticed no performance improvement or performance drop from it - if it holds up in testing it will be part of the -v17 release of numa/core.
Excellent. That gets rid of the last issue with numa/base :)
Signature · 7 lines
All rights reversed -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 18/19 mm/mpol: Use special PROT_NONE to migrate pages
In reply to Ingo MolnarFrom: Peter Zijlstra <[email protected]>
Combine our previous PROT_NONE, mpol_misplaced and migrate_misplaced_page() pieces into an effective migrate on fault scheme.
Note that (on x86) we rely on PROT_NONE pages being !present and avoid the TLB flush from try_to_unmap(TTU_MIGRATION). This greatly improves the page-migration performance.
--- mm/huge_memory.c | 41 +++++++++++++++++++++++++++++++++++- mm/memory.c | 63 ++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 85 insertions(+), 19 deletions(-)
mm/huge_memory.c +40 -1
@@ -18,6 +18,7 @@#include <linux/freezer.h> #include <linux/mman.h> #include <linux/pagemap.h> +#include <linux/migrate.h> #include <asm/tlb.h> #include <asm/pgalloc.h> #include "internal.h"
@@ -741,12 +742,48 @@ void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned int flags, pmd_t entry) {unsigned long haddr = address &HPAGE_PMD_MASK ; +struct page *page =NULL ; +int node;spin_lock (&mm->page_table_lock);if (unlikely (!pmd_same (*pmd, entry))) goto out_unlock; -/* do fancy stuff */ +if (unlikely (pmd_trans_splitting (entry))) { +spin_unlock (&mm->page_table_lock); +wait_split_huge_page (vma->anon_vma, pmd); +return ; + } + +#ifdef CONFIG_NUMA + page =pmd_page (entry); +VM_BUG_ON (!PageCompound (page) || !PageHead (page)); + +get_page (page); +spin_unlock (&mm->page_table_lock); + +/* +* XXX should we serialize against split_huge_page ? +*/ + + node =mpol_misplaced (page, vma, haddr); +if (node ==-1 ) + goto do_fixup; + +/* +* Due to lacking code to migrate thp pages, we'll split +* (which preserves the special PROT_NONE) and re-take the +* fault on the normal pages. +*/ +split_huge_page (page); +put_page (page); +return ; + +do_fixup: +spin_lock (&mm->page_table_lock); +if (unlikely (!pmd_same (*pmd, entry))) + goto out_unlock; +#endif /* change back to regular protection */ entry =pmd_modify (entry, vma->vm_page_prot);
@@ -755,6 +792,8 @@ void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, out_unlock:spin_unlock (&mm->page_table_lock); +if (page) +put_page (page); } int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
mm/memory.c +45 -18
94 lines not on this page · raw message
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 19/19 x86/mm: Completely drop the TLB flush from ptep_set_access_flags()
In reply to Ingo MolnarFrom: Rik van Riel <[email protected]>
Intel has an architectural guarantee that the TLB entry causing a page fault gets invalidated automatically. This means we should be able to drop the local TLB invalidation.
Because of the way other areas of the page fault code work, chances are good that all x86 CPUs do this. However, if someone somewhere has an x86 CPU that does not invalidate the TLB entry causing a page fault, this one-liner should be easy to revert - or a CPU model specific quirk could be added to retain this optimization on most CPUs.
[ Applied changelog massage and moved this last in the series,
to create bisection distance. ]
--- arch/x86/mm/pgtable.c | 1 - 1 file changed, 1 deletion(-)
arch/x86/mm/pgtable.c +0 -1
@@ -317,7 +317,6 @@ int ptep_set_access_flags(struct vm_area_struct *vma,if (changed && dirty) { *ptep = entry;pte_update_defer (vma->vm_mm, address, ptep); -__flush_tlb_one (address); }return changed;
Signature · 7 lines
1.7.11.7 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Just find imbalance issue on the patchset.
I write a one line program:
int main ()
{
int i;
for (i=0; i< 1; )
__asm__ __volatile__ ("nop");
}it was compiled with name pl and start it on my 2 socket * 4 cores * HT NUMA machine:
the cpu domain top like this:
domain 0: span 4,12 level SIBLING
groups: 4 (cpu_power = 589) 12 (cpu_power = 589)
domain 1: span 0,2,4,6,8,10,12,14 level MC
groups: 4,12 (cpu_power = 1178) 6,14 (cpu_power = 1178) 0,8
(cpu_power = 1178) 2,10 (cpu_power = 1178)
domain 2: span 0,2,4,6,8,10,12,14 level CPU
groups: 0,2,4,6,8,10,12,14 (cpu_power = 4712)
domain 3: span 0-15 level NUMA
groups: 0,2,4,6,8,10,12,14 (cpu_power = 4712) 1,3,5,7,9,11,13,15(cpu_power = 4712)
$for ((i=0; i< I; i++)); do ./pl & done when I = 2, they are running on cpu 0,12
I = 4, they are running on cpu 0,9,12,14
I = 8, they are running on cpu 0,4,9,10,11,12,13,14
Regards!
Alex
Quoted 80 lines · Ingo Molnar
This is the split-out series of
mm/patches that got no objections from the latest (v15) posting of numa/core. If everyone is still fine with these then these will be merge candidates for v3.8.I left out the more contentious policy bits that people are still arguing about.
The numa/base tree can also be found here:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitnuma/baseThanks,
Ingo
------------------->
Andrea Arcangeli (1):
numa, mm: Support NUMA hinting page faults from gup/gup_fastGerald Schaefer (1):
sched, numa, mm, s390/thp: Implementpmd_pgprot()for s390Ingo Molnar (1):
mm/pgprot: Move thepgprot_modify()fallback definition tomm.hLee Schermerhorn (3):
mm/mpol: AddMPOL_MF_NOOP
mm/mpol: Check for misplaced page
mm/mpol: AddMPOL_MF_LAZYPeter Zijlstra (7):
sched, numa, mm: Makefind_busiest_queue()a method sched, numa, mm: Describe the NUMA scheduling problem formally mm/thp: Preserve pgprot across huge page split mm/mpol: MakeMPOL_LOCALa real policy
mm/mpol: Create specialPROT_NONEinfrastructure mm/migrate: Introducemigrate_misplaced_page()mm/mpol: Use specialPROT_NONEto migrate pagesRalf Baechle (1):
sched, numa, mm, MIPS/thp: Addpmd_pgprot()implementationRik van Riel (5):
mm/generic: Only flush the local TLB inptep_set_access_flags()x86/mm: Only do a local tlb flush inptep_set_access_flags()x86/mm: Introducepte_accessible()
mm: Only flush the TLB when clearing an accessible pte x86/mm: Completely drop the TLB flush fromptep_set_access_flags()Documentation/scheduler/numa-problem.txt | 230 +++++++++++++++++++++++++++++++ arch/mips/include/asm/pgtable.h | 2 + arch/s390/include/asm/pgtable.h | 13 ++ arch/x86/include/asm/pgtable.h | 7 + arch/x86/mm/pgtable.c | 8 +- include/asm-generic/pgtable.h | 4 + include/linux/huge_mm.h | 19 +++ include/linux/mempolicy.h | 8 ++ include/linux/migrate.h | 7 + include/linux/migrate_mode.h | 3 + include/linux/mm.h | 32 +++++ include/uapi/linux/mempolicy.h | 16 ++- kernel/sched/fair.c | 20 +-- mm/huge_memory.c | 174 +++++++++++++++-------- mm/memory.c | 119 +++++++++++++++- mm/mempolicy.c | 143 +++++++++++++++---- mm/migrate.c | 85 ++++++++++-- mm/mprotect.c | 31 +++-- mm/pgtable-generic.c | 9 +- 19 files changed, 807 insertions(+), 123 deletions(-) create mode 100644 Documentation/scheduler/numa-problem.txt--
1.7.11.7--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Signature · 8 lines
Thanks
Alex
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>Quoted 21 lines · Alex Shi
Just find imbalance issue on the patchset.
I write a one line program:
int main (){ int i; for (i=0; i< 1; ) __asm__ __volatile__ ("nop"); }it was compiled with name pl and start it on my 2 socket * 4 cores * HT NUMA machine:
the cpu domain top like this:
domain 0: span 4,12 level SIBLING
groups: 4 (cpu_power= 589) 12 (cpu_power= 589)
domain 1: span 0,2,4,6,8,10,12,14 level MC
groups: 4,12 (cpu_power= 1178) 6,14 (cpu_power= 1178) 0,8
(cpu_power= 1178) 2,10 (cpu_power= 1178)
domain 2: span 0,2,4,6,8,10,12,14 level CPUgroups: 0,2,4,6,8,10,12,14 (cpu_power = 4712) domain 3: span 0-15 level NUMA groups: 0,2,4,6,8,10,12,14 (cpu_power = 4712) 1,3,5,7,9,11,13,15
Quoted 7 lines
(
cpu_power= 4712)$for ((i=0; i< I; i++)); do ./pl & done when I = 2, they are running on cpu 0,12
I = 4, they are running on cpu 0,9,12,14
I = 8, they are running on cpu 0,4,9,10,11,12,13,14
Ops, it was tested on latest V15 tip/master tree, head is a7b7a8ad4476bb641c8455a4e0d7d0fd3eb86f90
not on this series.
Sorry.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>