Files
UltraGrid/ldgm/src/ldgm-session.cpp
2021-03-25 15:08:03 +01:00

413 lines
12 KiB
C++

/*
* =====================================================================================
*
* Filename: ldgm-session.cpp
*
* Description:
*
* Version: 1.0
* Created: 04/12/2012 01:03:23 PM
* Revision: none
* Compiler: gcc
*
* Author: Milan Kabat (), kabat@ics.muni.cz
* Organization:
*
* =====================================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <sstream>
#include <string>
#include <string.h>
#include "ldgm-session.h"
#include "timer-util.h"
constexpr const int MAX_W = 128;
using namespace std;
/*
*--------------------------------------------------------------------------------------
* Class: LDGM_session
* Method: LDGM_session
* Description: constructor
*--------------------------------------------------------------------------------------
*/
void
LDGM_session::set_pcMatrix ( char* fname)
{
FILE *f;
f = fopen(fname, "rb");
if (!f)
{
printf ( "Error opening matrix file\n" );
printf ( "exiting\n" );
abort();
}
unsigned int k_f, m_f, w_f;
if (fscanf(f, "%d %d %d", &k_f, &m_f, &w_f) != 3) {
throw string("Parity matrix read error!");
}
// printf ( "In matrix file: K %d M %d Columns %d\n", k_f, m_f, w_f );
if (w_f < 2 || w_f > MAX_W) {
throw string("Invalid parameter in parity matrix (allowed range [2.." + to_string(MAX_W) + "])!");
}
if ( k_f != param_k || m_f != param_m)
{
ostringstream oss;
oss << "Parity matrix size mismatch\nExpected K = " << param_k << "% M = " << param_m <<
"\nReceived K = " << k_f << ", M = " << m_f << "\n";
throw oss.str();
}
if (fseek (f, 1, SEEK_CUR ) != 0) {
perror("fseek");
}
pcm = (int*) malloc(w_f*param_m*sizeof(int));
for ( int i = 0; i < (int)w_f*param_m; i++) {
if (fread ( pcm+i, sizeof(int), 1, f) != 1) {
throw string("Parity matrix read error!");
}
}
this->max_row_weight = w_f - 2; //w_f stores number of columns in adjacency list
/* for ( int i = 0; i < param_m; i++)
* {
* for ( int j = 0; j < w_f; j++)
* printf ( "[%3d]", (unsigned int)(pcm[i*w_f+j]) );
* printf ( "\n" );
* }
*/
fclose(f);
/*
* this->max_row_weight = 0;
* int max_weight = 0;
* for ( int i = 0; i < param_m; ++i) {
* for ( int j = 0; j < param_k; ++j) {
* if(*(matrix + i*param_k + j) == 1) {
* *(pcMatrix + i*param_k + j) = *(matrix + i*param_k + j);
* max_weight++;
* }
* }
* if ( max_weight > this->max_row_weight )
* this->max_row_weight = max_weight;
* max_weight = 0;
* }
*
* pcm = (int*) malloc (m*(max_row_weight+2)*sizeof(int*));
* struct coding_params params;
* params.m = m;
* params.k = k;
* params.max_row_weight = max_row_weight;
*
* make_compact_pcm ( matrix, pcm, params);
*/
return ;
} /* ----- end of method Coding_session::set_pcMatrix ----- */
char*
LDGM_session::encode_frame ( char* frame, int frame_size, int* out_buf_size )
{
//printf("encode_frame\n");
Timer_util interval;
interval.start();
int buf_size;
int ps;
short header_size = LDGM_session::HEADER_SIZE;
int align_coef = param_k*sizeof(int);
if ( (frame_size + header_size) % align_coef == 0 )
buf_size = frame_size + header_size;
else
buf_size = ( ( (frame_size + header_size) / align_coef ) + 1 ) * align_coef;
ps = buf_size/param_k;
packet_size = ps;
//printf ( "ps: %d\n", ps );
buf_size += param_m*ps;
*out_buf_size = buf_size;
void *out_buf;
out_buf = alloc_buf(buf_size);
if (!out_buf)
{
printf ( "Unable to allocate memory\n" );
return NULL;
}
memset(out_buf, 0, header_size);
memset((char*)out_buf + frame_size + header_size, 0, align_coef);
//Insert frame size and copy input data into buffer
int *hdr = (int*)out_buf;
*hdr = frame_size;
memcpy( ((char*)out_buf) + header_size, frame, frame_size);
//Timer_util t;
//printf("2buf_size %d\n",buf_size);
//printf("2packet_size %d\n",packet_size);
this->encode ( (char*)out_buf, ((char*)out_buf)+param_k*ps );
interval.end();
// printf("time: %e\n",elapsed/1000.0 );
this->elapsed_sum2 += interval.elapsed_time_ms();
this->no_frames2++;
return (char*)out_buf;
// printf ( "SSE: %.3lf\n", t.elapsed_time(start, end) );
/* void *out_buf_check;
* error = posix_memalign(&out_buf_check, 16, buf_size);
* memset(out_buf_check, 0, buf_size);
* hdr = (int*)out_buf_check;
* *hdr = frame_size;
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
* clock_gettime(CLOCK_MONOTONIC, &start);
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
* clock_gettime(CLOCK_MONOTONIC, &end);
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
*
* int e = memcmp(out_buf, out_buf_check, buf_size);
* printf ( "memcpy on parities: %d\n", e );
* char *a = (char*)out_buf;
* char *b = (char*)out_buf_check;
* bool equal = true;
* int idx = 0;
* for ( int i = 0; i < param_m*ps; i++)
* {
* if(a[i] != b[i])
* {
* idx = i;
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
* (unsigned char)b[i] );
* equal = false;
* }
* }
*
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
*/
// printf ( "\n\nEncoded block:\n" );
// printf ( "%-13s\v%10d B\n", "Frame hdr size:", header_size );
// printf ( "%-13s\v%10d B\n", "Frame size:", frame_size );
// printf ( "Padding size:\t%-d B\n", buf_size-frame_size-header_size-param_m*ps );
// printf ( "Parity size:\t%-d B\n", param_m*ps );
// printf ( "-------------------------------\n");
// printf ( "Total block size:\t%d B\n", buf_size );
// printf ( "Symbol size:\t%d\n\n\n", ps );
}
char*
LDGM_session::encode_hdr_frame ( char *my_hdr, int my_hdr_size, char* frame, int frame_size, int* out_buf_size )
{
int buf_size;
int ps;
short header_size = LDGM_session::HEADER_SIZE;
int overall_size = my_hdr_size + frame_size;
int align_coef = param_k*sizeof(int);
if ( (overall_size + header_size) % align_coef == 0 )
buf_size = overall_size + header_size;
else
buf_size = ( ( (overall_size + header_size) / align_coef ) + 1 ) * align_coef;
ps = buf_size/param_k;
packet_size = ps;
// printf ( "ps: %d\n", ps );
buf_size += param_m*ps;
*out_buf_size = buf_size;
void *out_buf;
out_buf = alloc_buf(buf_size);
if (!out_buf)
{
printf ( "Unable to allocate aligned memory\n" );
return NULL;
}
memset(out_buf, 0, buf_size);
//Insert frame size and copy input data into buffer
int32_t *hdr = (int32_t*)out_buf;
*hdr = overall_size;
memcpy( ((char*)out_buf) + header_size, my_hdr, my_hdr_size);
memcpy( ((char*)out_buf) + header_size + my_hdr_size, frame, frame_size);
#if 0
int my_frame_size=my_hdr_size+frame_size;
// printf("my_frame_size: %d\n",my_frame_size );
int crc;
crc = crc32buf((char*)out_buf+header_size,my_frame_size);
memcpy( ((char*)out_buf) + 4, &crc, 4);
memcpy( ((char*)out_buf) + 8, &my_frame_size, 4);
assert(LDGM_session::HEADER_SIZE >= 12);
#endif
Timer_util interval;
interval.start();
this->encode ( (char*)out_buf, ((char*)out_buf)+param_k*ps );
interval.end();
long elapsed;
elapsed = interval.elapsed_time_us();
// printf("time: %e\n",elapsed/1000.0 );
this->elapsed_sum2+=elapsed/1000.0;
this->no_frames2++;
// gettimeofday(&t1,0);
// long elapsed;
// elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
// // printf("time: %e\n",elapsed/1000.0 );
// this->elapsed_sum2+=elapsed/1000.0;
// this->no_frames2++;
// i++;
// if(i%100==0){
// printf("TIME GPU: %f ms\n",this->elapsed_sum2/(double)this->no_frames2 );
// printf("time: %f ms\n",elapsed/1000.0 );
// }
// printf ( "SSE: %.3lf\n", t.elapsed_time(start, end) );
/* void *out_buf_check;
* error = posix_memalign(&out_buf_check, 16, buf_size);
* memset(out_buf_check, 0, buf_size);
* hdr = (int*)out_buf_check;
* *hdr = frame_size;
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
* clock_gettime(CLOCK_MONOTONIC, &start);
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
* clock_gettime(CLOCK_MONOTONIC, &end);
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
*
* int e = memcmp(out_buf, out_buf_check, buf_size);
* printf ( "memcpy on parities: %d\n", e );
* char *a = (char*)out_buf;
* char *b = (char*)out_buf_check;
* bool equal = true;
* int idx = 0;
* for ( int i = 0; i < param_m*ps; i++)
* {
* if(a[i] != b[i])
* {
* idx = i;
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
* (unsigned char)b[i] );
* equal = false;
* }
* }
*
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
*/
// printf ( "\n\nEncoded block:\n" );
// printf ( "%-13s\v%10d B\n", "Frame hdr size:", header_size );
// printf ( "%-13s\v%10d B\n", "Frame size:", frame_size );
// printf ( "Padding size:\t%-d B\n", buf_size-frame_size-header_size-param_m*ps );
// printf ( "Parity size:\t%-d B\n", param_m*ps );
// printf ( "-------------------------------\n");
// printf ( "Total block size:\t%d B\n", buf_size );
// printf ( "Symbol size:\t%d\n\n\n", ps );
return (char*)out_buf;
}
/*
* === FUNCTION ======================================================================
* Name: create_edges
* Description:
* =====================================================================================
*/
void
LDGM_session::create_edges ( Tanner_graph *graph )
{
map<int, Node>::iterator it;
// printf ( "graph: %p, param_k: %d, param_m: %d\n", graph, param_k, param_m );
for ( int m = 0; m < param_m; ++m) {
for ( int k = 0; k < max_row_weight+2; ++k ) {
int idx = pcm [ m*(max_row_weight+2) + k];
if( idx > -1 ) {
it = graph->nodes.find(idx);
(*it).second.neighbours.push_back(param_k + param_m + m);
it = graph->nodes.find(param_k + param_m + m);
(*it).second.neighbours.push_back(idx);
}
}
}
/* it = graph->nodes.find(0);
* while ( it != graph->nodes.end() )
* {
* printf ( "\nneighbours of node %d: ", it->first );
* for (vector<int>::iterator i = it->second.neighbours.begin();
* i != it->second.neighbours.end(); ++i)
* printf ( "%d, ", *i );
* it++;
* }
*/
//add edges representing the staircase matrix
/* for ( int i = param_k + param_m; i < param_k + 2*param_m; ++i) {
* it = graph->nodes.find(i);
* (*it).second.neighbours.push_back(i - param_m);
* it = graph->nodes.find(i - param_m);
* (*it).second.neighbours.push_back(i);
* if(i > param_m + param_k) {
* it = graph->nodes.find(i);
* (*it).second.neighbours.push_back(i - param_m - 1);
* it = graph->nodes.find(i - param_m - 1);
* (*it).second.neighbours.push_back(i);
* }
* }
*/
return ;
} /* ----- end of function create_edges ----- */
bool
LDGM_session::needs_decoding ( Tanner_graph *graph )
{
for ( int i = 0; i < param_k; i++)
if( ! graph->nodes.find(i)->second.isDone() )
return true;
return false;
} /* ----- end of method LDGM_session::needs_decoding ----- */
LDGM_session::~LDGM_session() {
free(pcm);
}