Skip to content

Commit f5b9ebf

Browse files
committed
Starting on a BFS benchmark, but ran into problems with the deque module, so I used ports and channels as a queue in the simple sequential algorithm.
1 parent 0b2f2ca commit f5b9ebf

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

src/test/bench/graph500-bfs.rs

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/**
2+
3+
An implementation of the Graph500 Bread First Search problem in Rust.
4+
5+
*/
6+
7+
use std;
8+
import std::time;
9+
import std::map;
10+
import std::map::hashmap;
11+
import std::deque;
12+
import std::deque::t;
13+
import io::writer_util;
14+
import vec::extensions;
15+
import comm::*;
16+
17+
type node_id = i64;
18+
type graph = [map::set<node_id>];
19+
20+
iface queue<T: send> {
21+
fn add_back(T);
22+
fn pop_front() -> T;
23+
fn size() -> uint;
24+
}
25+
26+
#[doc="Creates a queue based on ports and channels.
27+
28+
This is admittedly not ideal, but it will help us work around the deque
29+
bugs for the time being."]
30+
fn create_queue<T: send>() -> queue<T> {
31+
type repr<T: send> = {
32+
p : port<T>,
33+
c : chan<T>,
34+
mut s : uint,
35+
};
36+
37+
let p = port();
38+
let c = chan(p);
39+
40+
impl<T: send> of queue<T> for repr<T> {
41+
fn add_back(x : T) {
42+
let x = x;
43+
send(self.c, x);
44+
self.s += 1u;
45+
}
46+
47+
fn pop_front() -> T {
48+
self.s -= 1u;
49+
recv(self.p)
50+
}
51+
52+
fn size() -> uint { self.s }
53+
}
54+
55+
let Q : repr<T> = { p : p, c : c, mut s : 0u };
56+
Q as queue::<T>
57+
}
58+
59+
fn make_edges(scale: uint, edgefactor: uint) -> [(node_id, node_id)] {
60+
let r = rand::rng();
61+
62+
fn choose_edge(i: node_id, j: node_id, scale: uint, r: rand::rng)
63+
-> (node_id, node_id) {
64+
65+
let A = 0.57;
66+
let B = 0.19;
67+
let C = 0.19;
68+
69+
if scale == 0u {
70+
(i, j)
71+
}
72+
else {
73+
let i = i * 2;
74+
let j = j * 2;
75+
let scale = scale - 1u;
76+
77+
let x = r.next_float();
78+
79+
if x < A {
80+
choose_edge(i, j, scale, r)
81+
}
82+
else {
83+
let x = x - A;
84+
if x < B {
85+
choose_edge(i + 1, j, scale, r)
86+
}
87+
else {
88+
let x = x - B;
89+
if x < C {
90+
choose_edge(i, j + 1, scale, r)
91+
}
92+
else {
93+
choose_edge(i + 1, j + 1, scale, r)
94+
}
95+
}
96+
}
97+
}
98+
}
99+
100+
vec::from_fn((1u << scale) * edgefactor) {|_i|
101+
choose_edge(0, 0, scale, r)
102+
}
103+
}
104+
105+
fn make_graph(N: uint, edges: [(node_id, node_id)]) -> graph {
106+
let graph = vec::from_fn(N) {|_i| map::int_hash() };
107+
108+
vec::each(edges) {|e|
109+
let (i, j) = e;
110+
map::set_add(graph[i], j);
111+
map::set_add(graph[j], i);
112+
true
113+
}
114+
115+
graph
116+
}
117+
118+
#[doc="Returns a vector of all the parents in the BFS tree rooted at key.
119+
120+
Nodes that are unreachable have a parent of -1."]
121+
fn bfs(graph: graph, key: node_id) -> [node_id] {
122+
let marks : [mut node_id]
123+
= vec::to_mut(vec::from_elem(vec::len(graph), -1));
124+
125+
let Q = create_queue();
126+
127+
Q.add_back(key);
128+
marks[key] = key;
129+
130+
while Q.size() > 0u {
131+
let t = Q.pop_front();
132+
133+
graph[t].each_key() {|k|
134+
if marks[k] == -1 {
135+
marks[k] = t;
136+
Q.add_back(k);
137+
}
138+
true
139+
};
140+
}
141+
142+
vec::from_mut(marks)
143+
}
144+
145+
fn main() {
146+
let scale = 14u;
147+
148+
let start = time::precise_time_s();
149+
let edges = make_edges(scale, 16u);
150+
let stop = time::precise_time_s();
151+
152+
io::stdout().write_line(#fmt("Generated %? edges in %? seconds.",
153+
vec::len(edges), stop - start));
154+
155+
let start = time::precise_time_s();
156+
let graph = make_graph(1u << scale, edges);
157+
let stop = time::precise_time_s();
158+
159+
let mut total_edges = 0u;
160+
vec::each(graph) {|edges| total_edges += edges.size(); true };
161+
162+
io::stdout().write_line(#fmt("Generated graph with %? edges in %? seconds.",
163+
total_edges / 2u,
164+
stop - start));
165+
166+
let start = time::precise_time_s();
167+
let bfs_tree = bfs(graph, 0);
168+
let stop = time::precise_time_s();
169+
170+
io::stdout().write_line(#fmt("BFS completed in %? seconds.",
171+
stop - start));
172+
}

0 commit comments

Comments
 (0)