Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3a7e97a

Browse files
committed
working on atomic add vector
1 parent e0908be commit 3a7e97a

14 files changed

Lines changed: 546 additions & 357 deletions

src/graphlab.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include <graphlab/graph/graph_includes.hpp>
3434
#include <graphlab/options/options_includes.hpp>
3535
#include <graphlab/logger/logger_includes.hpp>
36-
#include <graphlab/monitoring/monitoring_includes.hpp>
3736
#include <graphlab/parallel/parallel_includes.hpp>
3837
#include <graphlab/scheduler/scheduler_includes.hpp>
3938
#include <graphlab/serialization/serialization_includes.hpp>

src/graphlab/engine/engine_includes.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#include <graphlab/engine/iengine.hpp>
2727
#include <graphlab/engine/synchronous_engine.hpp>
28-
#include <graphlab/engine/asynchronous_consistent_engine.hpp>
28+
// #include <graphlab/engine/asynchronous_consistent_engine.hpp>
2929
#include <graphlab/engine/execution_status.hpp>
3030

3131
//#include <graphlab/engine/asynchronous_engine.hpp>

src/graphlab/engine/synchronous_engine.hpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
#include <deque>
3333
#include <boost/bind.hpp>
3434

35-
#include <graphlab/engine/iengine.hpp>x
35+
#include <graphlab/engine/iengine.hpp>
3636
#include <graphlab/vertex_program/icontext.hpp>
3737
#include <graphlab/engine/execution_status.hpp>
3838
#include <graphlab/options/graphlab_options.hpp>
39-
#include <graphlab/scheduler/vertex_map.hpp>
39+
#include <graphlab/parallel/atomic_add_vector.hpp>
4040
#include <graphlab/options/graphlab_options.hpp>
4141

4242
#include <graphlab/rpc/dc_dist_object.hpp>
@@ -59,7 +59,7 @@ namespace graphlab {
5959

6060
template<typename VertexProgram>
6161
class synchronous_engine :
62-
public iengine<VertexProgram>, icontex<VertexProgram> {
62+
public iengine<VertexProgram> {
6363

6464
public:
6565

@@ -77,6 +77,7 @@ namespace graphlab {
7777
typedef typename graph_type::lvid_type lvid_type;
7878

7979
typedef icontext<VertexProgram> icontext_type;
80+
typedef context<synchronous_engine> context_type;
8081

8182
private:
8283
dc_dist_object< synchronous_engine<VertexProgram> > rmi;
@@ -98,8 +99,8 @@ namespace graphlab {
9899
//! Locks for each vertex
99100
std::vector<spinlock> vlocks;
100101
std::vector<vertex_program_type> vertex_programs;
101-
vertex_map<message_type> messages;
102-
vertex_map<gather_type> gather_cache;
102+
atomic_add_vector<message_type> messages;
103+
atomic_add_vector<gather_type> gather_cache;
103104
dense_bitset active_vertices;
104105
dense_bitset active_next;
105106

@@ -381,12 +382,12 @@ namespace graphlab {
381382
void initialize_vertex_programs(size_t thread_id,
382383
barrier* barrier_ptr) {
383384
// For now we are using the engine as the context interface
384-
icontext_type& context = *this;
385+
context_type context(*this, graph);
385386
for(lvid_type lvid = thread_id; lvid < graph.num_local_vertices();
386387
lvid += threads.size()) {
387388
if(graph.l_is_master(lvid)) {
388389
local_vertex_type local_vertex = graph.l_vertex(lvid);
389-
vertex_programs[lvid].init(context, local_vertex);
390+
vertex_programs[lvid].init(context, vertex_type(local_vertex));
390391
send_vertex_program(lvid);
391392
}
392393
// Receive any inbound vertex programs
@@ -435,8 +436,11 @@ namespace graphlab {
435436
if(graph.l_is_master(lvid) && message.test_and_get(lvid, message)) {
436437
active_vertices.set_bit(lvid);
437438
local_vertex_type local_vertex = graph.l_vertex(lvid);
438-
vertex_programs[lvid].recv_message(context, local_vertex, message);
439-
if(vertex_programs[lvid].gather_edges() != NO_EDGES) {
439+
vertex_programs[lvid].recv_message(context,
440+
vertex_type(local_vertex),
441+
message);
442+
if(vertex_programs[lvid].gather_edges() != graphlab::NO_EDGES &&
443+
gather_cache.empty(lvid)) {
440444
active_next.set_bit(lvid);
441445
send_vertex_program(lvid);
442446
}
@@ -462,7 +466,7 @@ namespace graphlab {
462466
void execute_gathers() {
463467
graphlab::barrier barrier(threads.size());
464468
for(size_t i = 0; i < threads.size(); ++i) {
465-
threads.launch(boost::bind(&synchronous_engine::receive_messages,
469+
threads.launch(boost::bind(&synchronous_engine::execute_gathers,
466470
this, i, &barrier));
467471
}
468472
// Wait for all threads to finish
@@ -473,12 +477,16 @@ namespace graphlab {
473477
/**
474478
* Thread local receive message code
475479
*/
476-
void execute_gathers(size_t thread_id, barrier* barrier_ptr) {
477-
message_type message;
480+
void execute_gathers(size_t thread_id, barrier* barrier_ptr) {
481+
// First clear the gather cache
478482
for(lvid_type lvid = thread_id; lvid < graph.num_local_vertices();
479483
lvid += threads.size()) {
484+
if(active_next.get(lvid)) {
485+
//writing code here
486+
487+
}
480488
if(graph.l_is_master(lvid) && message.test_and_get(lvid, message)) {
481-
active_vertices.set_bit(lvid);
489+
482490
local_vertex_type local_vertex = graph.l_vertex(lvid);
483491
vertex_programs[lvid].recv_message(context, local_vertex, message);
484492
if(vertex_programs[lvid].gather_edges() != NO_EDGES) {
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/**
2+
* Copyright (c) 2009 Carnegie Mellon University.
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an "AS
13+
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language
15+
* governing permissions and limitations under the License.
16+
*
17+
* For more about this software visit:
18+
*
19+
* http://www.graphlab.ml.cmu.edu
20+
*
21+
*/
22+
23+
24+
/**
25+
* Also contains code that is Copyright 2011 Yahoo! Inc. All rights
26+
* reserved.
27+
*
28+
* Contributed under the iCLA for:
29+
* Joseph Gonzalez ([email protected])
30+
*
31+
*/
32+
33+
34+
35+
#ifndef GRAPHLAB_ATOMIC_ADD_VECTOR_HPP
36+
#define GRAPHLAB_ATOMIC_ADD_VECTOR_HPP
37+
38+
39+
#include <vector>
40+
41+
42+
#include <graphlab/parallel/pthread_tools.hpp>
43+
#include <graphlab/util/lock_free_pool.hpp>
44+
45+
46+
47+
namespace graphlab {
48+
49+
/**
50+
* \TODO DOCUMENT THIS CLASS
51+
*/
52+
53+
template<typename ValueType>
54+
class atomic_add_vector {
55+
public:
56+
typedef ValueType value_type;
57+
58+
// We needed a second "NULL" pointer value to indicate a value
59+
// that is being swapped.
60+
#define VALUE_PENDING (value_type*)(size_t)(-1)
61+
62+
private:
63+
lock_free_pool<value_type> pool;
64+
atomic<size_t> joincounter;
65+
66+
class atomic_box_type {
67+
private:
68+
value_type* volatile value_ptr;
69+
public:
70+
atomic_box_type() : value_ptr(NULL) { }
71+
72+
// void assign_unsafe(const atomic_box_type &other) {
73+
// value_ptr = other.value_ptr;
74+
// }
75+
76+
// bool peek_unsafe(const value_type& other) {
77+
// if (value_ptr != NULL) {
78+
// other = (*value_ptr);
79+
// return true;
80+
// } else { return false; }
81+
// }
82+
83+
// bool get_reference_unsafe(value_type*& ret) {
84+
// ret = value_ptr;
85+
// return ret != NULL;
86+
// }
87+
88+
// /** returns true if set for the first time */
89+
// inline bool set_unsafe(lock_free_pool<value_type>& pool,
90+
// const value_type& other,
91+
// atomic<size_t> &joincounter) {
92+
// if (value_ptr == NULL) {
93+
// value_ptr = pool.alloc();
94+
// (*value_ptr) = other;
95+
// return true;
96+
// } else {
97+
// (*value_ptr) += other;
98+
// joincounter.inc();
99+
// return false;
100+
// }
101+
// } // end of set_unsafe
102+
103+
/** returns true if set for the first time */
104+
inline bool set(lock_free_pool<value_type>& pool,
105+
const value_type& other,
106+
value_type& new_value,
107+
atomic<size_t>& joincounter) {
108+
bool ret = false;
109+
value_type toinsert = other;
110+
while(1) {
111+
value_type* vptr = VALUE_PENDING;
112+
// pull it out to process it
113+
atomic_exchange(value_ptr, vptr);
114+
// if there is nothing in there, set it
115+
// otherwise add it
116+
if (vptr == NULL) {
117+
vptr = pool.alloc();
118+
(*vptr) = toinsert;
119+
ret = true;
120+
} else if (vptr == VALUE_PENDING) {
121+
// a pending is in here. it is not ready for reading. try again.
122+
continue;
123+
} else { (*vptr) += toinsert; joincounter.inc(); }
124+
// swap it back in
125+
ASSERT_TRUE(vptr != VALUE_PENDING);
126+
new_value = *value_ptr;
127+
atomic_exchange(value_ptr, vptr);
128+
//aargh! I swapped something else out. Now we have to
129+
//try to put it back in
130+
if (__unlikely__(vptr != NULL && vptr != VALUE_PENDING)) {
131+
toinsert = (*vptr);
132+
} else { break; }
133+
}
134+
return ret;
135+
}
136+
137+
void clear(lock_free_pool<value_type>& pool) {
138+
value_type val; test_and_get(val);
139+
}
140+
141+
bool empty() { return value_ptr == NULL; }
142+
143+
inline bool test_and_get(lock_free_pool<value_type>& pool,
144+
value_type& r) {
145+
value_type* ret;
146+
while (1) {
147+
ret = value_ptr;
148+
if (ret == NULL) return false;
149+
else if (__likely__(ret != VALUE_PENDING)) {
150+
if (__likely__(atomic_compare_and_swap(value_ptr, ret,
151+
(value_type*)NULL))) {
152+
r = *ret;
153+
pool.free(ret);
154+
return true;
155+
}
156+
}
157+
}
158+
return false;
159+
} // end of test_and_get
160+
}; // end of atomic_box_type;
161+
162+
163+
164+
typedef std::vector< atomic_box_type > atomic_box_vec_type;
165+
atomic_box_vec_type atomic_box_vec;
166+
167+
168+
/** Not assignable */
169+
void operator=(const atomic_add_vector& other) { }
170+
171+
172+
public:
173+
/** Initialize the per vertex task set */
174+
atomic_add_vector(size_t num_vertices = 0) :
175+
pool(num_vertices + 256), atomic_box_vec(num_vertices) { }
176+
177+
/**
178+
* Resize the internal locks for a different graph
179+
*/
180+
void resize(size_t num_vertices) {
181+
atomic_box_vec.resize(num_vertices);
182+
pool.reset_pool(num_vertices + 256);
183+
}
184+
185+
/** Add a task to the set returning false if the task was already
186+
present. */
187+
bool add(const size_t& idx,
188+
const value_type& val) {
189+
ASSERT_LT(idx, atomic_box_vec.size());
190+
value_type new_value;
191+
return atomic_box_vec[idx].set(pool, val, new_value, joincounter);
192+
} // end of add task to set
193+
194+
195+
// /** Add a task to the set returning false if the task was already
196+
// present. */
197+
// bool add_unsafe(const size_t& idx,
198+
// const value_type& val) {
199+
// ASSERT_LT(idx, atomic_box_vec.size());
200+
// return atomic_box_vec[idx].set_unsafe(pool, val, joincounter);
201+
// } // end of add task to set
202+
203+
204+
bool add(const size_t& idx,
205+
const value_type& val,
206+
value_type& new_value) {
207+
ASSERT_LT(idx, atomic_box_vec.size());
208+
return atomic_box_vec[idx].set(pool, val, new_value, joincounter);
209+
} // end of add task to set
210+
211+
212+
213+
// /** Add a task to the set returning false if the task was already
214+
// present. Returns the priority of the task before and after
215+
// insertion. If the task did not exist prior to the add,
216+
// prev_priority = 0 */
217+
// bool add(const size_t& idx,
218+
// const value_type& val,
219+
// double& prev_priority,
220+
// double& new_priority) {
221+
// ASSERT_LT(idx, atomic_box_vec.size());
222+
// return atomic_box_vec[idx].set(pool, val, prev_priority, new_priority,
223+
// joincounter);
224+
// } // end of add task to set
225+
226+
// bool get_nondestructive_unsafe(const size_t& idx,
227+
// value_type& ret_val) {
228+
// return atomic_box_vec[idx].get_nondestructive_unsafe(ret_val);
229+
// }
230+
231+
// bool get_reference_unsafe(const size_t& idx,
232+
// value_type*& ret_val) {
233+
// return atomic_box_vec[idx].get_reference_unsafe(ret_val);
234+
// }
235+
236+
237+
bool test_and_get(const size_t& idx,
238+
value_type& ret_val) {
239+
ASSERT_LT(idx, atomic_box_vec.size());
240+
return atomic_box_vec[idx].test_and_get(pool, ret_val);
241+
}
242+
243+
bool empty(const size_t& idx) {
244+
return atomic_box_vec[idx].empty();
245+
}
246+
247+
size_t size() const {
248+
return atomic_box_vec.size();
249+
}
250+
251+
size_t num_joins() const {
252+
return joincounter.value;
253+
}
254+
255+
256+
void clear() {
257+
for (size_t i = 0; i < atomic_box_vec.size(); ++i) clear(i);
258+
}
259+
260+
void clear(size_t i) { atomic_box_vec[i].clear(pool); }
261+
262+
}; // end of vertex map
263+
264+
}; // end of namespace graphlab
265+
266+
#undef VALUE_PENDING
267+
268+
#endif
269+

0 commit comments

Comments
 (0)