-
Notifications
You must be signed in to change notification settings - Fork 165
/
Copy pathPageRank.C
105 lines (97 loc) · 3.58 KB
/
PageRank.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// This code is part of the project "Ligra: A Lightweight Graph Processing
// Framework for Shared Memory", presented at Principles and Practice of
// Parallel Programming, 2013.
// Copyright (c) 2013 Julian Shun and Guy Blelloch
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights (to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "ligra.h"
#include "math.h"
using namespace std;
template <class vertex>
struct PR_F {
double* p_curr, *p_next;
vertex* V;
PR_F(double* _p_curr, double* _p_next, vertex* _V) :
p_curr(_p_curr), p_next(_p_next), V(_V) {}
inline bool update(intT s, intT d){ //update function applies PageRank equation
p_next[d] += p_curr[s]/V[s].getOutDegree();
return 1;
}
inline bool updateAtomic (intT s, intT d) { //atomic Update
writeAdd(&p_next[d],p_curr[s]/V[s].getOutDegree());
return 1;
}
inline bool cond (intT d) { return cond_true(d); } //does nothing
};
//vertex map function to update its p value according to PageRank equation
struct PR_Vertex_F {
double damping;
double addedConstant;
double* p_curr;
double* p_next;
PR_Vertex_F(double* _p_curr, double* _p_next, double _damping, intT n) :
p_curr(_p_curr), p_next(_p_next),
damping(_damping), addedConstant((1-_damping)*(1/(double)n)){}
inline bool operator () (intT i) {
p_next[i] = damping*p_next[i] + addedConstant;
return 1;
}
};
//resets p
struct PR_Vertex_Reset {
double* p_curr;
PR_Vertex_Reset(double* _p_curr) :
p_curr(_p_curr) {}
inline bool operator () (intT i) {
p_curr[i] = 0.0;
return 1;
}
};
template <class vertex>
void Compute(graph<vertex> GA, intT r) {
const intT n = GA.n;
const double damping = 0.85;
const double epsilon = 0.0000001;
double one_over_n = 1/(double)n;
double* p_curr = newA(double,n);
{parallel_for(intT i=0;i<n;i++) p_curr[i] = one_over_n;}
double* p_next = newA(double,n);
{parallel_for(intT i=0;i<n;i++) p_next[i] = 0;} //0 if unchanged
bool* frontier = newA(bool,n);
{parallel_for(intT i=0;i<n;i++) frontier[i] = 1;}
vertexSubset Frontier(n,n,frontier);
while(1){
vertexSubset output = edgeMap(GA, Frontier, PR_F<vertex>(p_curr,p_next,GA.V),GA.m/20);
vertexMap(Frontier,PR_Vertex_F(p_curr,p_next,damping,n));
//compute L1-norm between p_curr and p_next
{parallel_for(intT i=0;i<n;i++) {
p_curr[i] = fabs(p_curr[i]-p_next[i]);
}}
double L1_norm = sequence::plusReduce(p_curr,n);
if(L1_norm < epsilon) break;
//reset p_curr
vertexMap(Frontier,PR_Vertex_Reset(p_curr));
swap(p_curr,p_next);
Frontier.del();
Frontier = output;
}
Frontier.del();
free(p_curr); free(p_next);
}