Remove excess clone()'ing

Improves performance by 15%
This commit is contained in:
Christopher Berner 2019-02-12 22:11:19 -08:00
parent 2efe39012f
commit f85d6c5075
7 changed files with 38 additions and 22 deletions

@ -12,6 +12,7 @@ use matrix::OctetMatrix;
use octet::Octet;
use octets::count_ones_and_nonzeros;
use arraymap::ArrayMap;
use util::get_both_indices;
use petgraph::prelude::*;
use petgraph::algo::condensation;
@ -261,8 +262,8 @@ impl IntermediateSymbolDecoder {
node_lookup.insert(col, node);
}
for row in rows_with_two_ones.clone() {
if hdpc_rows[row] {
for row in rows_with_two_ones.iter() {
if hdpc_rows[*row] {
continue;
}
let mut ones = vec![];
@ -273,7 +274,7 @@ impl IntermediateSymbolDecoder {
// are the edges of the graph that connect the two columns (nodes) in the positions
// of the two ones."
// This part of the matrix is over GF(2), so "nonzero entries" is equivalent to "ones"
if self.A.get(row, col) == Octet::one() {
if self.A.get(*row, col) == Octet::one() {
ones.push(col);
}
if ones.len() == 2 {
@ -282,7 +283,7 @@ impl IntermediateSymbolDecoder {
}
let node1 = node_lookup.get(ones[0]);
let node2 = node_lookup.get(ones[1]);
g.add_edge(node1, node2, row);
g.add_edge(node1, node2, *row);
}
let connected_components = condensation(g.clone(), true);
@ -548,14 +549,14 @@ impl IntermediateSymbolDecoder {
}
if self.X.get(row, col) == Octet::one() {
self.debug_symbol_add_ops += 1;
let temp = self.D[self.d[col]].clone();
self.D[self.d[row]] += &temp;
let (dest, temp) = get_both_indices(&mut self.D, self.d[row], self.d[col]);
*dest += temp;
}
else {
self.debug_symbol_mul_ops += 1;
self.debug_symbol_add_ops += 1;
let temp = self.D[self.d[col]].clone();
self.D[self.d[row]].fused_addassign_mul_scalar(&temp, &self.X.get(row, col));
let (dest, temp) = get_both_indices(&mut self.D, self.d[row], self.d[col]);
dest.fused_addassign_mul_scalar(temp, &self.X.get(row, col));
}
}
}
@ -785,14 +786,14 @@ impl IntermediateSymbolDecoder {
fn fma_rows(&mut self, i: usize, iprime: usize, beta: Octet) {
if beta == Octet::one() {
self.debug_symbol_add_ops += 1;
let temp = self.D[self.d[i]].clone();
self.D[self.d[iprime]] += &temp;
let (dest, temp) = get_both_indices(&mut self.D, self.d[iprime], self.d[i]);
*dest += temp;
}
else {
self.debug_symbol_add_ops += 1;
self.debug_symbol_mul_ops += 1;
let temp = self.D[self.d[i]].clone();
self.D[self.d[iprime]].fused_addassign_mul_scalar(&temp, &beta);
let (dest, temp) = get_both_indices(&mut self.D, self.d[iprime], self.d[i]);
dest.fused_addassign_mul_scalar(&temp, &beta);
}
self.A.fma_rows(iprime, i, &beta);
}

@ -2,6 +2,7 @@ extern crate petgraph;
extern crate primal;
extern crate raptorq;
mod util;
mod arraymap;
mod octets;
#[allow(dead_code)]

@ -51,7 +51,7 @@ impl SourceBlockEncoder {
let tuple = intermediate_tuple(self.source_symbols.len() as u32, start_encoding_symbol_id + i);
result.push(EncodingPacket {
payload_id: PayloadId::new(self.source_block_id, start_encoding_symbol_id + i).unwrap(),
symbol: enc(self.source_symbols.len() as u32, self.intermediate_symbols.clone(), tuple)
symbol: enc(self.source_symbols.len() as u32, &self.intermediate_symbols, tuple)
});
}
result
@ -87,7 +87,7 @@ fn gen_intermediate_symbols(extended_source_block: Vec<Symbol>, symbol_size: usi
// Enc[] function, as defined in section 5.3.5.3
fn enc(source_block_symbols: u32,
intermediate_symbols: Vec<Symbol>,
intermediate_symbols: &Vec<Symbol>,
source_tuple: (u32, u32, u32, u32, u32, u32)) -> Symbol {
let w = num_lt_symbols(source_block_symbols);
let p = num_pi_symbols(source_block_symbols);
@ -164,7 +164,7 @@ mod tests {
// See section 5.3.3.4.1, item 1.
for i in 0..extended_source_symbols.len() {
let tuple = intermediate_tuple(NUM_SYMBOLS, i as u32);
let encoded = enc(NUM_SYMBOLS, intermediate_symbols.clone(), tuple);
let encoded = enc(NUM_SYMBOLS, &intermediate_symbols, tuple);
assert_eq!(extended_source_symbols[i].clone(), encoded);
}
}

@ -1,6 +1,7 @@
extern crate petgraph;
extern crate primal;
mod util;
mod arraymap;
mod systematic_constants;
mod rng;

@ -3,6 +3,7 @@ use octet::Octet;
use octets::fused_addassign_mul_scalar;
use octets::add_assign;
use symbol::Symbol;
use util::get_both_indices;
#[derive(Clone, Debug, PartialEq)]
pub struct OctetMatrix {
@ -102,13 +103,14 @@ impl OctetMatrix {
}
pub fn fma_rows(&mut self, dest: usize, multiplicand: usize, scalar: &Octet) {
// TODO: find a way to remove this clone()?
let temp = self.elements[multiplicand].clone();
assert_ne!(dest, multiplicand);
let (dest_row, temp_row) = get_both_indices(&mut self.elements, dest, multiplicand);
if *scalar == Octet::one() {
add_assign(&mut self.elements[dest], &temp);
add_assign(dest_row, temp_row);
}
else {
fused_addassign_mul_scalar(&mut self.elements[dest], &temp, scalar);
fused_addassign_mul_scalar(dest_row, temp_row, scalar);
}
}

@ -26,8 +26,8 @@ impl Symbol {
self.value.len()
}
pub fn bytes(&self) -> Vec<u8> {
self.value.clone()
pub fn bytes(&self) -> &Vec<u8> {
&self.value
}
pub fn mulassign_scalar(&mut self, scalar: &Octet) {
@ -67,6 +67,6 @@ mod tests {
let symbol2 = Symbol::new(data2);
symbol1 += &symbol2;
assert_eq!(result, symbol1.bytes());
assert_eq!(result, *symbol1.bytes());
}
}

11
src/util.rs Normal file

@ -0,0 +1,11 @@
pub fn get_both_indices<T>(vector: &mut Vec<T>, i: usize, j: usize) -> (&mut T, &mut T) {
assert_ne!(i, j);
if i < j {
let (first, last) = vector.split_at_mut(j);
return (&mut first[i], &mut last[0])
}
else {
let (first, last) = vector.split_at_mut(i);
return (&mut last[0], &mut first[j])
}
}