Efficient Parallel Functional Programming with Hierarchical Memory Management
Sam Westrick Carnegie Mellon University
Joint work with: Ram Raghunathan, Adrien Guatto, Stefan Muller, Rohan Yadav, Umut Acar, Guy Blelloch, Matthew Fluet
Efficient Parallel Functional Programming with Hierarchical Memory - - PowerPoint PPT Presentation
Efficient Parallel Functional Programming with Hierarchical Memory Management Sam Westrick Carnegie Mellon University Joint work with: Ram Raghunathan, Adrien Guatto, Stefan Muller, Rohan Yadav, Umut Acar, Guy Blelloch, Matthew Fluet Setting
Joint work with: Ram Raghunathan, Adrien Guatto, Stefan Muller, Rohan Yadav, Umut Acar, Guy Blelloch, Matthew Fluet
(no side-effects, no concurrency, no race conditions)
(speedup w.r.t. fastest sequential solution)
but not absolute efficiency
high rate of allocation, heavy reliance upon garbage collection
(not just functional)
fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
msort [2,4,3,1] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
par (fn () => msort [2,4], fn () => msort [3,1]) fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
msort [2,4] msort [3,1] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
msort [2] msort [4] msort [3] msort [1] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
[2] [4] [3] [1] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
merge [2] [4] merge [3] [1] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
[2,4] [1,3] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
merge [2,4] [1,3] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
[1,2,3,4] fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
X Y Z
join fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
X Y Z
join fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
fork (spawn)
X
fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
fork (spawn) fresh empty heaps fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
X
A L R fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
A L R fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end fork (spawn)
A L R L1 R1 L2 R2 fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end B1 B2 join
fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
A L R L1 R1 L2 R2 B1 B2
fun msort A = if length A < 2 then A else let val (L, R) = splitMid A val (L’, R’) = par (fn () => msort L, fn () => msort R) val B = merge L’ R’ in B end
A L R L1 R1 L2 R2 B B1 B2
in strict purely functional programs, all pointers either point up or are internal
[Raghunathan et al, ICFP’16]
in strict purely functional programs, all pointers either point up or are internal
[Raghunathan et al, ICFP’16]
in strict purely functional programs, all pointers either point up or are internal
[Raghunathan et al, ICFP’16]
in strict purely functional programs, all pointers either point up or are internal
[Raghunathan et al, ICFP’16]
pick a subtree reorganize, compact, etc. inside subtree
pick a subtree reorganize, compact, etc. inside subtree
dangling pointer
[]
r let val r = ref [] fun f () = (r := 0 :: !r) fun g () = (r := 1 :: !r) in par (f, g) end
[]
r let val r = ref [] fun f () = (r := 0 :: !r) fun g () = (r := 1 :: !r) in par (f, g) end
[]
r let val r = ref [] fun f () = (r := 0 :: !r) fun g () = (r := 1 :: !r) in par (f, g) end
[]
r let val r = ref [] fun f () = (r := 0 :: !r) fun g () = (r := 1 :: !r) in par (f, g) end
1
[]
r let val r = ref [] fun f () = (r := 0 :: !r) fun g () = (r := 1 :: !r) in par (f, g) end
1
[Guatto et al, PPoPP’18]
[Westrick et al, work in progress]
val par : (unit -> ‘a) * (unit -> ‘b) -> ‘a * ‘b
merge heaps in O(1) time
0.00 0.50 1.00 1.50 2.00 f i b t a b u l a t e m a p m a p
n
l a c e s c a n r e d u c e f i l t e r s a m p l e s
t m e r g e s
t d m m d e d u p h i s t
r a m b a r n e s
u t a l l
e a r e s t
18 36 54 72 90
f i b t a b u l a t e m a p m a p
n
l a c e s c a n r e d u c e f i l t e r s a m p l e s
t m e r g e s
t d m m d e d u p h i s t
r a m b a r n e s
u t a l l
e a r e s t