Пример #1
0
// Test to make sure that Longhair works well with input ordered like this for
// k = 4 and m = 2
// 0
// 2
// 3
// 5
// 6
void order_test() {
	int block_bytes = 8 * 162; // a multiple of 8

	Abyssinian prng;
	prng.Initialize(m_clock.msec(), Clock::cycles());

	int block_count = 4;
	int recovery_block_count = 2;

	u8 *data = new u8[block_bytes * block_count];
	u8 *recovery_blocks = new u8[block_bytes * recovery_block_count];
	Block *blocks = new Block[block_count];

	const u8 *data_ptrs[256];
	for (int ii = 0; ii < block_count; ++ii) {
		data_ptrs[ii] = data + ii * block_bytes;
	}

	for (int ii = 0; ii < block_bytes * block_count; ++ii) {
		data[ii] = (u8)prng.Next();
	}

	assert(!cauchy_256_encode(block_count, recovery_block_count, data_ptrs, recovery_blocks, block_bytes));

	for (int ii = 0; ii < block_count; ++ii) {
		blocks[ii].data = (u8*)data_ptrs[ii];
		blocks[ii].row = (u8)ii;
	}

	int rem = block_count;
	for (int ii = 0; ii < recovery_block_count; ++ii) {
		int jj = prng.Next() % rem;

		--rem;

		for (int kk = jj; kk < rem; ++kk) {
			blocks[kk].data = blocks[kk + 1].data;
			blocks[kk].row = blocks[kk + 1].row;
		}

		blocks[rem].data = recovery_blocks + ii * block_bytes;
		blocks[rem].row = block_count + ii;
	}

	cout << "Before decode:" << endl;
	for (int ii = 0; ii < block_count; ++ii) {
		cout << (int)blocks[ii].row << endl;
	}

	assert(!cauchy_256_decode(block_count, recovery_block_count, blocks, block_bytes));

	cout << "After decode:" << endl;
	for (int ii = 0; ii < block_count; ++ii) {
		cout << (int)blocks[ii].row << endl;
	}

	for (int ii = 0; ii < block_count; ++ii) {
		assert(!memcmp(blocks[ii].data, data_ptrs[blocks[ii].row], block_bytes));
	}
}
Пример #2
0
void GF256Matrix::Fill()
{
	Abyssinian prng;
	prng.Initialize(_seed);

	u8 *row = _matrix;
	int words = _pitch * _n;
	while (words--)
	{
		*row++ = (u8)prng.Next();
	}
}
Пример #3
0
int main() {
	m_clock.OnInitialize();

	cauchy_256_init();

	m_clock.usec();

	cout << "Cauchy RS Codec Unit Tester" << endl;

	order_test();

	int block_bytes = 8 * 162; // a multiple of 8

	cout << "Using " << block_bytes << " bytes per block (ie. packet/chunk size); must be a multiple of 8 bytes" << endl;

	Abyssinian prng;
	prng.Initialize(m_clock.msec(), Clock::cycles());

	u8 heat_map[256 * 256] = { 0 };

	for (int block_count = 1; block_count < 256; ++block_count) {
#ifdef CAT_REASONABLE_RECOVERY_COUNT
		for (int recovery_block_count = 1; recovery_block_count <= (block_count / 2) && recovery_block_count < (256 - block_count); ++recovery_block_count) {
#else
		for (int recovery_block_count = 1; recovery_block_count < (256 - block_count); ++recovery_block_count) {
#endif
			u8 *data = new u8[block_bytes * block_count];
			u8 *recovery_blocks = new u8[block_bytes * recovery_block_count];
			Block *blocks = new Block[block_count];

			const u8 *data_ptrs[256];
			for (int ii = 0; ii < block_count; ++ii) {
				data_ptrs[ii] = data + ii * block_bytes;
			}

			double sum_encode = 0;

			int erasures_count;
#ifdef CAT_WORST_CASE_BENCHMARK
            erasures_count = recovery_block_count;
            if (block_count < erasures_count)
            {
                erasures_count = block_count;
            }
            {
#else
# ifdef CAT_ENCODE_TIMES_ONLY
			for (erasures_count = 1; erasures_count <= 4 && erasures_count <= recovery_block_count && erasures_count <= block_count; ++erasures_count) {
# else
			for (erasures_count = 1; erasures_count <= recovery_block_count && erasures_count <= block_count; ++erasures_count) {
# endif
#endif
				for (int ii = 0; ii < block_bytes * block_count; ++ii) {
					data[ii] = (u8)prng.Next();
				}

				double t0 = m_clock.usec();

				assert(!cauchy_256_encode(block_count, recovery_block_count, data_ptrs, recovery_blocks, block_bytes));

				double t1 = m_clock.usec();
				double encode_time = t1 - t0;
				sum_encode += encode_time;

				cout << "Encoded k=" << block_count << " data blocks with m=" << recovery_block_count << " recovery blocks in " << encode_time << " usec : " << (block_bytes * block_count / encode_time) << " MB/s" << endl;

#ifndef CAT_ENCODE_TIMES_ONLY
				for (int ii = 0; ii < erasures_count; ++ii) {
					int erasure_index = recovery_block_count - ii - 1;
					blocks[ii].data = recovery_blocks + erasure_index * block_bytes;
					blocks[ii].row = block_count + erasure_index;
				}

				for (int ii = erasures_count; ii < block_count; ++ii) {
					blocks[ii].data = data + ii * block_bytes;
					blocks[ii].row = ii;
				}

				t0 = m_clock.usec();

				assert(!cauchy_256_decode(block_count, recovery_block_count, blocks, block_bytes));

				t1 = m_clock.usec();
				double decode_time = t1 - t0;

				cout << "+ Decoded " << erasures_count << " erasures in " << decode_time << " usec : " << (block_bytes * block_count / decode_time) << " MB/s" << endl;
/*
				for (int ii = 0; ii < erasures_count; ++ii) {
					const u8 *orig = data + ii * block_bytes;
					print(orig, block_bytes / 8);
					print(blocks[ii].data, block_bytes / 8);
				}
*/
				for (int ii = 0; ii < erasures_count; ++ii) {
					const u8 *orig = data + ii * block_bytes;
					assert(!memcmp(blocks[ii].data, orig, block_bytes));
				}
#endif // CAT_ENCODE_TIMES_ONLY
			}

			double avg_encode = sum_encode / erasures_count;
			int speed = block_bytes * block_count / avg_encode;

			u8 map_value = 0;

			if (speed < 10) {
				map_value = 1;
			} else if (speed < 50) {
				map_value = 2;
			} else if (speed < 100) {
				map_value = 3;
			} else if (speed < 200) {
				map_value = 4;
			} else if (speed < 300) {
				map_value = 5;
			} else if (speed < 400) {
				map_value = 6;
			} else if (speed < 500) {
				map_value = 7;
			} else {
				map_value = 8;
			}

			heat_map[block_count * 256 + recovery_block_count] = map_value;

			delete []data;
			delete []recovery_blocks;
			delete []blocks;
		}
	}

	ofstream file;
	file.open("docs/heatmap.txt");

	for (int ii = 0; ii < 256; ++ii) {
		for (int jj = 0; jj < 256; ++jj) {
			u8 map_value = heat_map[ii * 256 + jj];

			file << (int)map_value << " ";
		}
		file << endl;
	}

	m_clock.OnFinalize();

	return 0;
}
Пример #4
0
int main()
{
	m_clock.OnInitialize();

	//FindBadDenseSeeds();

	for (int ii = 64; ii <= 64000; ii += 1000)
	{
		int block_count = ii;
		int block_bytes = 1500;
		int message_bytes = block_bytes * block_count;
		u8 *message = new u8[message_bytes];
		u8 *message_out = new u8[message_bytes];
		u8 *block = new u8[block_bytes];

		for (int ii = 0; ii < message_bytes; ++ii)
		{
			message[ii] = ii;
		}

		wirehair::Encoder encoder;

		double start = m_clock.usec();
		wirehair::Result r = encoder.BeginEncode(message, message_bytes, block_bytes);
		double end = m_clock.usec();

		if (r)
		{
			cout << "-- FAIL! N=" << encoder.BlockCount() << " encoder.BeginEncode error " << wirehair::GetResultString(r) << endl;
			cin.get();
			continue;
		}
		else
		{
			double mbytes = message_bytes / 1000000.;

			cout << ">> OKAY! N=" << encoder.BlockCount() << "(" << mbytes << " MB) encoder.BeginEncode in " << end - start << " usec, " << message_bytes / (end - start) << " MB/s" << endl;
			//cin.get();
		}

		Abyssinian prng;
		cat::wirehair::Decoder decoder;

		u32 overhead_sum = 0, overhead_trials = 0;
		u32 drop_seed = 50002;
		double time_sum = 0;
		const int trials = 1000;
		for (int jj = 0; jj < trials; ++jj)
		{
			int blocks_needed = 0;

			wirehair::Result s = decoder.BeginDecode(message_out, message_bytes, block_bytes);
			if (s)
			{
				cout << "-- FAIL! N=" << decoder.BlockCount() << " decoder.BeginDecode error " << wirehair::GetResultString(s) << endl;
				cin.get();
				return 1;
			}

			prng.Initialize(drop_seed);
			for (u32 id = 0;; ++id)
			{
				if (prng.Next() & 1) continue;
				encoder.Encode(id, block);

				++blocks_needed;
				double start = m_clock.usec();
				wirehair::Result r = decoder.Decode(id, block);
				double end = m_clock.usec();

				if (r != wirehair::R_MORE_BLOCKS)
				{
					if (r == wirehair::R_WIN)
					{
						u32 overhead = blocks_needed - decoder.BlockCount();
						overhead_sum += overhead;
						++overhead_trials;

						//cout << ">> OKAY! N=" << decoder.BlockCount() << " decoder.Decode in " << end - start << " usec, " << message_bytes / (end - start) << " MB/s after " << overhead << " extra blocks.  Average extra = " << overhead_sum / (double)overhead_trials << ". Seed = " << drop_seed << endl;
						time_sum += end - start;

						if (!memcmp(message, message_out, message_bytes))
						{
							//cout << "Match!" << endl;
						}
						else
						{
							cout << "FAAAAAIL! Seed = " << drop_seed << endl;

							for (int ii = 0; ii < message_bytes; ++ii)
							{
								if (message_out[ii] != message[ii])
									cout << ii << " : " << (int)message_out[ii] << endl;
							}

							cin.get();
						}
					}
					else
					{
						cout << "-- FAIL!  N=" << decoder.BlockCount() << " decoder.Decode error " << wirehair::GetResultString(r) << " from drop seed " << drop_seed << endl;

						overhead_sum += 1;
						++overhead_trials;

						//cin.get();
					}

					//cin.get();
					break;
				}
			}

			++drop_seed;
		}

		double avg_time = time_sum / trials;
		double avg_overhead = overhead_sum / (double)overhead_trials;
		double avg_bytes = message_bytes * (decoder.BlockCount() + avg_overhead) / (double)decoder.BlockCount() - message_bytes;
		cout << "N=" << decoder.BlockCount() << " decoder.Decode in " << avg_time << " usec, " << message_bytes / avg_time << " MB/s.  Average overhead = " << avg_overhead << " (" << avg_bytes << " bytes)" << endl;
	}

	m_clock.OnFinalize();

	return 0;
}