add yield version of parallel-reduce
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 21 Jun 2022 13:08:08 +0000 (14:08 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 21 Jun 2022 13:08:08 +0000 (14:08 +0100)
openpower/sv/preduce.py

index 815def6b7fa237e268a41ed48af221781cba9070..5fb4f26f6d349e5fdf0d15cb50f66a4da6fa40e4 100644 (file)
@@ -1,7 +1,7 @@
 from copy import copy
 
 def preduce(vl, vec, pred):
-    vec = copy(vec) # must not damage predicate
+    vec = copy(vec)
     pred = copy(pred) # must not damage predicate
     step = 1
     print(" start", step, pred, vec)
@@ -18,10 +18,12 @@ def preduce(vl, vec, pred):
         print("   row", step, pred, vec)
     return vec
 
+
 def preducei(vl, vec, pred):
+    vec = copy(vec)
     pred = copy(pred) # must not damage predicate
     step = 1
-    ix = list(range(vl))
+    ix = list(range(vl)) # indices move rather than copy data
     print(" start", step, pred, vec)
     while step < vl:
         step *= 2
@@ -33,9 +35,34 @@ def preducei(vl, vec, pred):
             if pred[ci] and other_pred:
                 vec[ci] += vec[oi]
             elif other_pred:
-                ix[i] = oi
+                ix[i] = oi # leave data in-place, copy index instead
             pred[ci] |= other_pred
         print("   row", step, pred, vec, ix)
+    return vec
+
+
+def preduce_yield(vl, vec, pred):
+    pred = copy(pred) # must not damage predicate
+    step = 1
+    ix = list(range(vl))
+    while step < vl:
+        step *= 2
+        for i in range(0, vl, step):
+            other = i + step // 2
+            ci = ix[i]
+            oi = ix[other] if other < vl else None
+            other_pred = other < vl and pred[oi]
+            if pred[ci] and other_pred:
+                yield ci, oi
+            elif other_pred:
+                ix[i] = oi
+            pred[ci] |= other_pred
+
+
+def preduce_y(vl, vec, pred):
+   for i, other in preduce_yield(vl, vec, pred):
+       vec[i] += vec[other]
+
 
 if __name__ == '__main__':
     vec = [1, 2, 3, 4, 9, 5, 6]
@@ -43,8 +70,24 @@ if __name__ == '__main__':
     print (vec)
     res = preduce(len(vec), vec, prd)
     print (res)
-    preducei(len(vec), vec, prd)
+    res2 = preducei(len(vec), vec, prd)
+    print (res2)
+    print ()
+    preduce_y(len(vec), vec, prd)
+    print (vec)
+    print ()
+    assert vec == res2
+
+    vec = [1, 2, 3, 4, 9, 5, 6]
+    prd = [1, 0, 0, 1, 1, 0, 1]
+    print (vec)
+    res = preduce(len(vec), vec, prd)
+    print (res)
+    res2 = preducei(len(vec), vec, prd)
+    print (res2)
+    print ()
+    preduce_y(len(vec), vec, prd)
     print (vec)
     print ()
-    assert vec == res
+    assert vec == res2