Skip to content

Instantly share code, notes, and snippets.

@Mouq
Last active December 25, 2015 13:59
Show Gist options
  • Save Mouq/6987932 to your computer and use it in GitHub Desktop.
Save Mouq/6987932 to your computer and use it in GitHub Desktop.
# Attempt at making the program correct, though it makes
# the program run 4.5 times slower (on my machine).
# In fact, I think it works because the threads
# spend so much time updating the hash
# that the chance of them both selecting the same
# indices AND executing the swap at the same time
# are made an order of magnitude more negligible.
use v6;
sub run (Int $vecs, Int $items, Int $threads, Int $iters) {
my @vec-refs = [(state$)++ xx $items] xx $vecs;
my %touched;
my sub swap {
my $a := @vec-refs[(^*).pick][(^*).pick];
my $b := @vec-refs[(^*).pick][(^*).pick];
repeat { #`( nothing ) } while $a|$b === any %touched.keys;
%touched{$a,$b} = True, True;
($a,$b)=($b,$a);
%touched{$a,$b}:delete;
}
my sub report {
say <( )>.join: (<[ ]>.join($_) for @vec-refs);
say "Distinct:", +@vec-refs.map(*.list).uniq;
}
report;
await Promise.allof($threads Rxx async { swap() for ^$iters });
report;
}
run 100, 10, 10, 100000;
; Original program, from the Clojure Wikipedia page
; https://en.wikipedia.org/wiki/Clojure#Examples
(defn run [nvecs nitems nthreads niters]
(let [vec-refs (vec (map (comp ref vec)
(partition nitems (range (* nvecs nitems)))))
swap #(let [v1 (rand-int nvecs)
v2 (rand-int nvecs)
i1 (rand-int nitems)
i2 (rand-int nitems)]
(dosync
(let [temp (nth @(vec-refs v1) i1)]
(alter (vec-refs v1) assoc i1 (nth @(vec-refs v2) i2))
(alter (vec-refs v2) assoc i2 temp))))
report #(do
(prn (map deref vec-refs))
(println "Distinct:"
(count (distinct (apply concat (map deref vec-refs))))))]
(report)
(dorun (apply pcalls (repeat nthreads #(dotimes [_ niters] (swap)))))
(report)))
(run 100 10 10 100000)
# Translation from Clojure
# Issues: There isn't (?) a native way to modify
# @vec-refs without any simultaneously editing
# one of the same positions on
# Clojure uses (alter ...) for this
# Jakudo often ends up with `Distinct: 999`
use v6;
sub run (Int $vecs, Int $items, Int $threads, Int $iters) {
my @vec-refs = [(state$)++ xx $items] xx $vecs;
my sub swap {
my $a := @vec-refs[(^*).pick][(^*).pick];
my $b := @vec-refs[(^*).pick][(^*).pick];
($a,$b)=($b,$a);
}
my sub report {
say <( )>.join: (<[ ]>.join($_) for @vec-refs);
say "Distinct:", +@vec-refs.map(*.list).uniq;
}
report;
await Promise.allof($threads Rxx async { swap() xx $iters });
report;
}
run 100, 10, 10, 100000;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment