Commit 20650dad authored by Renaud Pacalet's avatar Renaud Pacalet
Browse files

Optimize data structures for SCMS and SCMSFP (in each row store only CN-to-VN...

Optimize data structures for SCMS and SCMSFP (in each row store only CN-to-VN and VN-to-CN lessages corresponding to active variable nodes in the row)
parent b1fba363
......@@ -29,9 +29,9 @@
###############
CC := gcc
CFLAGS := -no-pie -pg -c -MMD -O3 --std=c99
CFLAGS := -c -MMD -O3 --std=c99
LD := gcc
LDFLAGS := -no-pie -pg
LDFLAGS :=
LIBS := -lm
BUILDDIR := build
......
......@@ -437,26 +437,36 @@ unsigned scms_decode(mod2sparse *H, double *lratio, char *dblk, char *pchk, doub
return n;
}
/* initialize */
void scms_init( mod2sparse *H, double *lratio, char *dblk, double *bprb, scms_data *sd) {
int N;
int M;
int col;
int row, col, i;
double max = 0.0;
mod2entry *e;
N = mod2sparse_cols(H);
M = mod2sparse_rows(H);
// Find max row degrees
for(row = 0; row < M; row++) {
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) // for all active columns in row
;
sd->b[row] = chk_alloc (i, sizeof **(sd->b));
sd->a[row] = chk_alloc (i, sizeof **(sd->a));
}
for (col = 0; col<N; col++) {
if (bprb) bprb[col] = 1 - 1/(1+lratio[col]);
dblk[col] = lratio[col]>=1;
sd->g[col] = -log(lratio[col]); // channel observations as Log Likelihood Ratios (LLR)
if(fabs(sd->g[col]) > max) max = fabs(sd->g[col]);
for(int row = 0; row < M; row++) {
sd->b[row][col] = 0.0; // CN
sd->a[row][col] = sd->g[col]; // VN
}
}
for(int row = 0; row < M; row++) {
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
sd->b[row][i] = 0.0; // CN
sd->a[row][i] = sd->g[col]; // VN
}
}
#ifdef DEBUG
fprintf(stderr, "max(LLR) = %lf\n", max);
......@@ -469,7 +479,7 @@ void scms_iter(mod2sparse *H, double *lratio, char *dblk, double *bprb, scms_dat
int N, M;
double dtmp; // temporary double
int itmp; // temporary integer
int col, row;
int i, col, row;
/* computation of CN (sd->b[row][col]) rely on 4 values computed from VNs of same row (sd->a[row][col]):
min1: first minimum of absolute values of VNs
......@@ -493,28 +503,28 @@ void scms_iter(mod2sparse *H, double *lratio, char *dblk, double *bprb, scms_dat
sp = 1;
// compute product of signs of VNs, argmin of absolute values of VNs, first and second minimum of absolute values of VNs
for (e = mod2sparse_first_in_row(H,row); !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e)) { // for all active columns in row
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
sp = sp * SCMS_SIGN_MP(sd->a[row][col]); // compute product of signs of VNs
sp = sp * SCMS_SIGN_MP(sd->a[row][i]); // compute product of signs of VNs
// compute argmin of absolute values of VNs, first and second minimum of absolute values of VNs
dtmp = fabs(sd->a[row][col]); // absolute value of VN
dtmp = fabs(sd->a[row][i]); // absolute value of VN
if(dtmp < min1 || min1 < 0.0) { // if less than first min or if not yet valid
min2 = min1;
min1 = dtmp;
idx = col;
idx = i;
} else if(dtmp < min2 || min2 < 0.0) { // if less than second min or if not yet valid
min2 = dtmp;
}
}
// compute CNs with Min-Sum (MS) kernel:
// sd->b[row][col] = \prod_{i\in H(row), i\neq col}(\sgn(sd->a[row][i])\times\min_{i\in H(row), i\neq col}(\lvert sd->a[row][i]\rvert)
for (e = mod2sparse_first_in_row(H,row); !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e)) { // for all active columns in row
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
itmp = sp * SCMS_SIGN_MP(sd->a[row][col]); // sign of CN
if(idx == col) {
sd->b[row][col] = itmp * min2; // magnitude of CN
itmp = sp * SCMS_SIGN_MP(sd->a[row][i]); // sign of CN
if(idx == i) {
sd->b[row][i] = itmp * min2; // magnitude of CN
} else {
sd->b[row][col] = itmp * min1;
sd->b[row][i] = itmp * min1;
}
}
}
......@@ -522,21 +532,27 @@ void scms_iter(mod2sparse *H, double *lratio, char *dblk, double *bprb, scms_dat
for (col = 0; col<N; col++) { // for all columns
// compute new a-posteriori information: sd->h[col] = sd->g[col] + \sum_{i\in H(col)}(sd->b[i][col])
sd->h[col] = sd->g[col];
for (e = mod2sparse_first_in_col(H,col); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) { // for all active rows in column
row = e->row; // row index
sd->h[col] += sd->b[row][col];
}
for (row = 0; row<M; row++) { // for all rows
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
sd->h[col] += sd->b[row][i];
}
for (e = mod2sparse_first_in_col(H,col); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) { // for all active rows in column
row = e->row; // row index
}
for (row = 0; row<M; row++) { // for all rows
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
// compute new VNs: sd->a[row][col] = sd->h[col] - sd->b[row][col]
dtmp = sd->h[col] - sd->b[row][col];
dtmp = sd->h[col] - sd->b[row][i];
// erase VN if sign changed since last iteration, except if already erased during last iteration
if((SCMS_SIGN_MP(sd->a[row][col]) != SCMS_SIGN_MP(dtmp)) && (sd->a[row][col] != 0.0)) {
sd->a[row][col] = 0.0; // erase VN
if((SCMS_SIGN_MP(sd->a[row][i]) != SCMS_SIGN_MP(dtmp)) && (sd->a[row][i] != 0.0)) {
sd->a[row][i] = 0.0; // erase VN
} else {
sd->a[row][col] = dtmp;
sd->a[row][i] = dtmp;
}
}
}
for (col = 0; col<N; col++) { // for all columns
// compute new bit probabilities
if (bprb) bprb[col] = 1 - 1/(1+exp(-sd->h[col]));
// compute new hard decisions
......@@ -584,21 +600,32 @@ unsigned scmsfp_decode(mod2sparse *H, double *lratio, char *dblk, char *pchk, do
void scmsfp_init(mod2sparse *H, double *lratio, char *dblk, double *bprb, scmsfp_data *sd) {
int N;
int M;
int col;
int row, col, i;
double dtmp;
mod2entry *e;
N = mod2sparse_cols(H);
M = mod2sparse_rows(H);
// Find max row degrees
for(row = 0; row < M; row++) {
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) // for all active columns in row
;
sd->b[row] = chk_alloc (i, sizeof **(sd->b));
sd->a[row] = chk_alloc (i, sizeof **(sd->a));
}
for (col = 0; col<N; col++) {
if (bprb) bprb[col] = 1 - 1/(1+lratio[col]);
dblk[col] = lratio[col]>=1;
dtmp = -log(lratio[col]);
sd->g[col] = scms_saturate(round(dtmp), sd->size);
for(int row = 0; row < M; row++) {
sd->b[row][col] = 0;
sd->a[row][col] = sd->g[col];
}
}
for(int row = 0; row < M; row++) {
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
sd->b[row][i] = 0; // CN
sd->a[row][i] = sd->g[col]; // VN
}
}
}
......@@ -607,7 +634,7 @@ void scmsfp_iter(mod2sparse *H, double *lratio, char *dblk, double *bprb, scmsfp
mod2entry *e;
int N, M;
int64_t itmp;
int col, row;
int i, col, row;
int64_t min1;
int64_t min2;
int idx;
......@@ -622,44 +649,52 @@ void scmsfp_iter(mod2sparse *H, double *lratio, char *dblk, double *bprb, scmsfp
idx = 0;
sp = 1;
for (e = mod2sparse_first_in_row(H,row); !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e)) {
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) {
col = e->col;
sp = sp * SCMS_SIGN_MP(sd->a[row][col]);
itmp = SCMS_ABS(sd->a[row][col]);
sp = sp * SCMS_SIGN_MP(sd->a[row][i]);
itmp = SCMS_ABS(sd->a[row][i]);
if(itmp < min1 || min1 < 0) {
min2 = min1;
min1 = itmp;
idx = col;
idx = i;
} else if(itmp < min2 || min2 < 0) {
min2 = itmp;
}
}
for (e = mod2sparse_first_in_row(H,row); !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e)) {
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) {
col = e->col;
itmp = sp * SCMS_SIGN_MP(sd->a[row][col]);
if(idx == col) {
sd->b[row][col] = itmp * min2;
itmp = sp * SCMS_SIGN_MP(sd->a[row][i]);
if(idx == i) {
sd->b[row][i] = itmp * min2;
} else {
sd->b[row][col] = itmp * min1;
sd->b[row][i] = itmp * min1;
}
}
}
for (col = 0; col<N; col++) {
sd->h[col] = sd->g[col];
for (e = mod2sparse_first_in_col(H,col); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) {
row = e->row;
sd->h[col] += sd->b[row][col];
}
for (row = 0; row<M; row++) { // for all rows
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
sd->h[col] += sd->b[row][i];
}
}
for (col = 0; col<N; col++) {
sd->h[col] = scms_saturate(sd->h[col], sd->size);
for (e = mod2sparse_first_in_col(H,col); !mod2sparse_at_end(e); e = mod2sparse_next_in_col(e)) {
row = e->row;
itmp = scms_saturate(sd->h[col] - sd->b[row][col], sd->size);
if((SCMS_SIGN_MP(sd->a[row][col]) != SCMS_SIGN_MP(itmp)) && (sd->a[row][col] != 0)) {
sd->a[row][col] = 0;
}
for (row = 0; row<M; row++) { // for all rows
for (e = mod2sparse_first_in_row(H,row), i = 0; !mod2sparse_at_end(e); e = mod2sparse_next_in_row(e), i++) { // for all active columns in row
col = e->col; // column index
itmp = scms_saturate(sd->h[col] - sd->b[row][i], sd->size);
if((SCMS_SIGN_MP(sd->a[row][i]) != SCMS_SIGN_MP(itmp)) && (sd->a[row][i] != 0)) {
sd->a[row][i] = 0;
} else {
sd->a[row][col] = itmp;
sd->a[row][i] = itmp;
}
}
}
for (col = 0; col<N; col++) { // for all columns
if (bprb) bprb[col] = 1 - 1/(1+exp(-sd->h[col]));
dblk[col] = sd->h[col] < 0;
}
......
......@@ -267,19 +267,11 @@ int main
sd.h = chk_alloc (N, sizeof *sd.h);
sd.b = chk_alloc (M, sizeof *sd.b);
sd.a = chk_alloc (M, sizeof *sd.a);
for(int row = 0; row < M; row++) {
sd.b[row] = chk_alloc (N, sizeof **sd.b);
sd.a[row] = chk_alloc (N, sizeof **sd.a);
}
sdfp.g = chk_alloc (N, sizeof *sdfp.g);
sdfp.h = chk_alloc (N, sizeof *sdfp.h);
sdfp.b = chk_alloc (M, sizeof *sdfp.b);
sdfp.a = chk_alloc (M, sizeof *sdfp.a);
for(int row = 0; row < M; row++) {
sdfp.b[row] = chk_alloc (N, sizeof **sdfp.b);
sdfp.a[row] = chk_alloc (N, sizeof **sdfp.a);
}
sdla.r = chk_alloc (M, sizeof *sdla.r);
sdla.p = chk_alloc (N, sizeof *sdla.p);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment