-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathParallel_AMP.cpp
More file actions
executable file
·143 lines (111 loc) · 3.39 KB
/
Copy pathParallel_AMP.cpp
File metadata and controls
executable file
·143 lines (111 loc) · 3.39 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <unistd.h> // sleep
#include <armadillo>
#include <vector>
#include <deque>
#include <algorithm> // std::min
#include "Functions.h"
using namespace arma;
using namespace std;
vec eta(const vec &v, const double tau){
vec out(size(v),fill::zeros);
uvec ind = find(abs(v) > tau);
out(ind) = sign(v(ind))%(abs(v(ind)) - tau );
return out;
}
vec eta_deriv(const vec &v, const double tau){
vec out(size(v),fill::zeros);
uvec ind = find(abs(v) > tau);
out(ind).ones();
return out;
}
vec eta(const vec &v, const vec tau){
vec out(size(v),fill::zeros);
uvec ind = find(abs(v) > tau);
out(ind) = sign(v(ind))%(abs(v(ind)) - tau(ind) );
return out;
}
vec eta_deriv(const vec &v, const vec tau){
vec out(size(v),fill::zeros);
uvec ind = find(abs(v) > tau);
out(ind).ones();
return out;
}
vec AMP(const mat &A, const vec &y, const int sparsity, const unsigned int max_iter,
const double tol, unsigned int &num_iters, const simulation_parameters simulation_params){
const unsigned int N = A.n_cols; // signal dimension
const unsigned int M = y.n_elem; // number of measurements
//const double delta = double(num_measurements)/sig_dim;
unsigned int i = 0;
vec x_t(N,fill::zeros);
vec z_t = y;
double tau = .1;
bool done = false;
vec pseudo_data (N,fill::zeros);
while(!done){
i++;
z_t = y - A*x_t + z_t * sum (eta_deriv( pseudo_data,tau) ) / M;
pseudo_data = A.t() * z_t + x_t;
tau = tau * sum(eta_deriv(pseudo_data,tau)) / M;
x_t = eta(pseudo_data,tau) ;
if (norm (y - A*x_t) < tol || i >= max_iter){
done = true;
}
}
num_iters = i;
return x_t;
}
// J. Zhu, R. Pilgrim and D. Baron, "An overview of multi-processor approximate message passing,"
// http://ieeexplore.ieee.org/document/7926166/
vec R_MP_AMP(const mat &A, const vec &y, const int sparsity, const unsigned int max_iter,
const double tol, unsigned int &num_iters, const simulation_parameters simulation_params){
uvec slow_cores;
set_slow_cores(slow_cores, simulation_params);
const unsigned int N = A.n_cols;
const unsigned int M = y.n_elem;
const unsigned int P = simulation_params.num_cores;
unsigned int i = 0;
bool done = false;
vec x_t(N,fill::zeros);
double g_t = M;
double tau = .1;
vector <vec> pseudo_data (P,vec(N,fill::zeros));
// parallel section of the code starts here
#pragma omp parallel num_threads(simulation_params.num_cores)
{
// initializing variables in local memory
const int p = omp_get_thread_num();
mat A_p = A.rows(M*p/P , M*(p+1)/P -1 );
vec y_p = y.subvec( M*p/P , M*(p+1)/P -1 );
vec z_t_p = y_p;
// R_MP_AMP itearations
while(!done){
//AT processor p:
z_t_p = y_p - A_p*x_t + z_t_p * g_t / M;
pseudo_data[p] = A_p.t() * z_t_p + x_t/P;
//slow cores sleep for simulation_params.sleep_slow_cores microseconds
if (any( slow_cores == omp_get_thread_num()) ){
usleep(simulation_params.sleep_slow_cores);
}
#pragma omp barrier
//AT fusion center:
#pragma omp single
{
i++;
vec pseudo_data_total(N,fill::zeros);
for (unsigned int j = 0; j < P; j++){
pseudo_data_total = pseudo_data_total + pseudo_data[j];
}
tau = tau * sum(eta_deriv(pseudo_data_total,tau)) / M;
g_t = sum(eta_deriv(pseudo_data_total,tau));
x_t = eta(pseudo_data_total,tau);
if (norm (y - A*x_t) < tol || i >= max_iter){
done = true;
}
}
#pragma omp barrier
}
// parallel section of the code ends here
}
num_iters = i;
return x_t;
}