VCluster_unit_tests.hpp 12.8 KB
Newer Older
incardon's avatar
incardon committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * VCluster_unit_tests.hpp
 *
 *  Created on: May 9, 2015
 *      Author: Pietro incardona
 */

#ifndef VCLUSTER_UNIT_TESTS_HPP_
#define VCLUSTER_UNIT_TESTS_HPP_

#include "VCluster.hpp"
#include <sstream>
#include <boost/test/included/unit_test.hpp>
#include "timer.hpp"
incardon's avatar
incardon committed
15
#include <random>
incardon's avatar
incardon committed
16
17
18

#define VERBOSE_TEST

incardon's avatar
incardon committed
19
#define N_TRY 2
incardon's avatar
incardon committed
20
#define N_LOOP 67108864
incardon's avatar
incardon committed
21
22
23
24
25
#define BUFF_STEP 524288

BOOST_AUTO_TEST_SUITE( VCluster_test )

size_t global_step = 0;
incardon's avatar
incardon committed
26
size_t global_rank;
incardon's avatar
incardon committed
27
28
29

// Alloc the buffer to receive the messages

incardon's avatar
incardon committed
30
void * msg_alloc(size_t msg_i ,size_t total_msg, size_t total_p, size_t i,size_t ri, void * ptr)
incardon's avatar
incardon committed
31
32
33
{
	openfpm::vector<openfpm::vector<unsigned char>> * v = static_cast<openfpm::vector<openfpm::vector<unsigned char>> *>(ptr);

34
35
36
37
	if (global_v_cluster->getProcessingUnits() <= 8)
		BOOST_REQUIRE_EQUAL(total_p,global_v_cluster->getProcessingUnits()-1);
	else
		BOOST_REQUIRE_EQUAL(total_p,8);
incardon's avatar
incardon committed
38

incardon's avatar
incardon committed
39
	BOOST_REQUIRE_EQUAL(msg_i, global_step);
incardon's avatar
incardon committed
40
41
42
43
44
45
46
47
48
49
	v->get(i).resize(msg_i);

	return &(v->get(i).get(0));
}

// Alloc the buffer to receive the messages

size_t id = 0;
openfpm::vector<size_t> prc_recv;

incardon's avatar
incardon committed
50
void * msg_alloc2(size_t msg_i ,size_t total_msg, size_t total_p, size_t i, size_t ri, void * ptr)
incardon's avatar
incardon committed
51
52
53
54
55
56
{
	openfpm::vector<openfpm::vector<unsigned char>> * v = static_cast<openfpm::vector<openfpm::vector<unsigned char>> *>(ptr);

	v->resize(total_p);
	prc_recv.resize(total_p);

incardon's avatar
incardon committed
57
	BOOST_REQUIRE_EQUAL(msg_i, global_step);
incardon's avatar
incardon committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

	id++;
	v->get(id-1).resize(msg_i);
	prc_recv.get(id-1) = i;
	return &(v->get(id-1).get(0));
}

BOOST_AUTO_TEST_CASE( VCluster_use_reductions)
{
	init_global_v_cluster(&boost::unit_test::framework::master_test_suite().argc,&boost::unit_test::framework::master_test_suite().argv);
	Vcluster & vcl = *global_v_cluster;

	unsigned char uc = 1;
	char c = 1;
	short s = 1;
	unsigned short us = 1;
	int i = 1;
	unsigned int ui = 1;
	long int li = 1;
	unsigned long int uli = 1;
	float f = 1;
	double d = 1;

incardon's avatar
incardon committed
81
82
83
84
85
86
87
88
89
90
91
92
	unsigned char uc_max = vcl.getProcessUnitID();
	char c_max = vcl.getProcessUnitID();
	short s_max = vcl.getProcessUnitID();
	unsigned short us_max = vcl.getProcessUnitID();
	int i_max = vcl.getProcessUnitID();
	unsigned int ui_max = vcl.getProcessUnitID();
	long int li_max = vcl.getProcessUnitID();
	unsigned long int uli_max = vcl.getProcessUnitID();
	float f_max = vcl.getProcessUnitID();
	double d_max = vcl.getProcessUnitID();

	// Sum reductions
incardon's avatar
incardon committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
	if ( vcl.getProcessingUnits() < 128 )
		vcl.reduce(c);
	if ( vcl.getProcessingUnits() < 256 )
		vcl.reduce(uc);
	if ( vcl.getProcessingUnits() < 32768 )
		vcl.reduce(s);
	if ( vcl.getProcessingUnits() < 65536 )
		vcl.reduce(us);
	if ( vcl.getProcessingUnits() < 2147483648 )
		vcl.reduce(i);
	if ( vcl.getProcessingUnits() < 4294967296 )
		vcl.reduce(ui);
	vcl.reduce(li);
	vcl.reduce(uli);
	vcl.reduce(f);
	vcl.reduce(d);
incardon's avatar
incardon committed
109
110
111
112
113
114
115

	// Max reduction
	if ( vcl.getProcessingUnits() < 128 )
		vcl.max(c_max);
	if ( vcl.getProcessingUnits() < 256 )
		vcl.max(uc_max);
	if ( vcl.getProcessingUnits() < 32768 )
incardon's avatar
incardon committed
116
		vcl.max(s_max);
incardon's avatar
incardon committed
117
	if ( vcl.getProcessingUnits() < 65536 )
incardon's avatar
incardon committed
118
		vcl.max(us_max);
incardon's avatar
incardon committed
119
	if ( vcl.getProcessingUnits() < 2147483648 )
incardon's avatar
incardon committed
120
		vcl.max(i_max);
incardon's avatar
incardon committed
121
	if ( vcl.getProcessingUnits() < 4294967296 )
incardon's avatar
incardon committed
122
123
124
125
126
		vcl.max(ui_max);
	vcl.max(li_max);
	vcl.max(uli_max);
	vcl.max(f_max);
	vcl.max(d_max);
incardon's avatar
incardon committed
127
128
129
	vcl.execute();

	if ( vcl.getProcessingUnits() < 128 )
incardon's avatar
incardon committed
130
	{BOOST_REQUIRE_EQUAL(c_max,vcl.getProcessingUnits()-1);}
incardon's avatar
incardon committed
131
	if ( vcl.getProcessingUnits() < 256 )
incardon's avatar
incardon committed
132
	{BOOST_REQUIRE_EQUAL(uc_max,vcl.getProcessingUnits()-1);}
incardon's avatar
incardon committed
133
	if ( vcl.getProcessingUnits() < 32768 )
incardon's avatar
incardon committed
134
	{BOOST_REQUIRE_EQUAL(s_max,vcl.getProcessingUnits()-1);}
incardon's avatar
incardon committed
135
	if ( vcl.getProcessingUnits() < 65536 )
incardon's avatar
incardon committed
136
	{BOOST_REQUIRE_EQUAL(us_max,vcl.getProcessingUnits()-1);}
incardon's avatar
incardon committed
137
	if ( vcl.getProcessingUnits() < 2147483648 )
incardon's avatar
incardon committed
138
	{BOOST_REQUIRE_EQUAL(i_max,vcl.getProcessingUnits()-1);}
incardon's avatar
incardon committed
139
	if ( vcl.getProcessingUnits() < 4294967296 )
incardon's avatar
incardon committed
140
	{BOOST_REQUIRE_EQUAL(ui_max,vcl.getProcessingUnits()-1);}
incardon's avatar
incardon committed
141

incardon's avatar
incardon committed
142
143
144
145
	BOOST_REQUIRE_EQUAL(li_max,vcl.getProcessingUnits()-1);
	BOOST_REQUIRE_EQUAL(uli_max,vcl.getProcessingUnits()-1);
	BOOST_REQUIRE_EQUAL(f_max,vcl.getProcessingUnits()-1);
	BOOST_REQUIRE_EQUAL(d_max,vcl.getProcessingUnits()-1);
incardon's avatar
incardon committed
146
147
148
149
150
151
152
153
154
155
156
157
}


BOOST_AUTO_TEST_CASE( VCluster_use_sendrecv)
{
	std::cout << "VCluster unit test start" << "\n";
	init_global_v_cluster(&boost::unit_test::framework::master_test_suite().argc,&boost::unit_test::framework::master_test_suite().argv);

	Vcluster & vcl = *global_v_cluster;

	// send/recv messages

incardon's avatar
incardon committed
158
	global_rank = vcl.getProcessUnitID();
incardon's avatar
incardon committed
159
160
	size_t n_proc = vcl.getProcessingUnits();

incardon's avatar
incardon committed
161
	// Checking short communication pattern
incardon's avatar
incardon committed
162
163
164

	for (size_t s = 0 ; s < N_TRY ; s++)
	{
incardon's avatar
incardon committed
165
		for (size_t j = 32 ; j < N_LOOP ; j*=2)
incardon's avatar
incardon committed
166
167
168
169
170
171
172
173
174
		{
			global_step = j;
			// send message
			openfpm::vector<openfpm::vector<unsigned char>> message;
			// recv message
			openfpm::vector<openfpm::vector<unsigned char>> recv_message(n_proc);

			openfpm::vector<size_t> prc;

175
			for (size_t i = 0 ; i < 8  && i < n_proc ; i++)
incardon's avatar
incardon committed
176
			{
177
178
				size_t p_id = (i + 1 + vcl.getProcessUnitID()) % n_proc;
				if (p_id != vcl.getProcessUnitID())
incardon's avatar
incardon committed
179
				{
180
					prc.add(p_id);
incardon's avatar
incardon committed
181
182
					message.add();
					std::ostringstream msg;
183
					msg << "Hello from " << vcl.getProcessUnitID() << " to " << p_id;
incardon's avatar
incardon committed
184
					std::string str(msg.str());
incardon's avatar
incardon committed
185
186
					message.last().resize(j);
					memset(message.last().getPointer(),0,j);
incardon's avatar
incardon committed
187
188
189
190
					std::copy(str.c_str(),&(str.c_str())[msg.str().size()],&(message.last().get(0)));
				}
			}

incardon's avatar
incardon committed
191
			recv_message.resize(n_proc);
incardon's avatar
incardon committed
192
193
194
195
			// The pattern is not really random preallocate the receive buffer
			for (size_t i = 0 ; i < 8  && i < n_proc ; i++)
			{
				long int p_id = vcl.getProcessUnitID() - i - 1;
incardon's avatar
incardon committed
196
197
198
199
200
				if (p_id < 0)
					p_id += n_proc;
				else
					p_id = p_id % n_proc;

201
				if (p_id != (long int)vcl.getProcessUnitID())
incardon's avatar
incardon committed
202
					recv_message.get(p_id).resize(j);
incardon's avatar
incardon committed
203
204
			}

incardon's avatar
incardon committed
205
206
207
208
209
210
211
212
213
214
#ifdef VERBOSE_TEST
			timer t;
			t.start();
#endif

			vcl.sendrecvMultipleMessages(prc,message,msg_alloc,&recv_message);

#ifdef VERBOSE_TEST
			t.stop();
			double clk = t.getwct();
incardon's avatar
incardon committed
215
			double clk_max = clk;
incardon's avatar
incardon committed
216

incardon's avatar
incardon committed
217
			size_t size_send_recv = 2 * j * (prc.size());
incardon's avatar
incardon committed
218
			vcl.reduce(size_send_recv);
incardon's avatar
incardon committed
219
			vcl.max(clk_max);
incardon's avatar
incardon committed
220
221
			vcl.execute();

incardon's avatar
incardon committed
222
			if (vcl.getProcessUnitID() == 0)
incardon's avatar
incardon committed
223
				std::cout << "(Short pattern: )Buffer size: " << j << "    Bandwidth (Average): " << size_send_recv / vcl.getProcessingUnits() / clk / 1e6 << " MB/s  " << "    Bandwidth (Total): " << size_send_recv / clk / 1e6 << " MB/s    Clock: " << clk << "   Clock MAX: " << clk_max <<"\n";
incardon's avatar
incardon committed
224
225
226
#endif

			// Check the message
227
			for (size_t i = 0 ; i < 8  && i < n_proc ; i++)
incardon's avatar
incardon committed
228
			{
229
230
231
232
233
234
				long int p_id = vcl.getProcessUnitID() - i - 1;
				if (p_id < 0)
					p_id += n_proc;
				else
					p_id = p_id % n_proc;

235
				if (p_id != (long int)vcl.getProcessUnitID())
incardon's avatar
incardon committed
236
237
				{
					std::ostringstream msg;
238
					msg << "Hello from " << p_id << " to " << vcl.getProcessUnitID();
incardon's avatar
incardon committed
239
					std::string str(msg.str());
240
					BOOST_REQUIRE_EQUAL(std::equal(str.c_str(),str.c_str() + str.size() ,&(recv_message.get(p_id).get(0))),true);
incardon's avatar
incardon committed
241
242
243
				}
				else
				{
244
					BOOST_REQUIRE_EQUAL(0,recv_message.get(p_id).size());
incardon's avatar
incardon committed
245
246
247
248
249
250
				}
			}
		}

		std::srand(global_v_cluster->getProcessUnitID());
		std::default_random_engine eg;
251
		std::uniform_int_distribution<int> d(0,n_proc/8);
incardon's avatar
incardon committed
252

incardon's avatar
incardon committed
253
		// Check random pattern (maximum 16 processors)
incardon's avatar
incardon committed
254

incardon's avatar
incardon committed
255
		for (size_t j = 32 ; j < N_LOOP && n_proc < 16 ; j*=2)
incardon's avatar
incardon committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
		{
			global_step = j;
			// original send
			openfpm::vector<size_t> o_send;
			// send message
			openfpm::vector<openfpm::vector<unsigned char>> message;
			// recv message
			openfpm::vector<openfpm::vector<unsigned char>> recv_message;

			openfpm::vector<size_t> prc;

			for (size_t i = 0 ; i < n_proc ; i++)
			{
				// randomly with witch processor communicate
270
				if (d(eg) == 0)
incardon's avatar
incardon committed
271
272
273
274
275
276
277
278
279
				{
					prc.add(i);
					o_send.add(i);
					message.add();
					std::ostringstream msg;
					msg << "Hello from " << vcl.getProcessUnitID() << " to " << i;
					std::string str(msg.str());
					message.last().resize(str.size());
					std::copy(str.c_str(),&(str.c_str())[msg.str().size()],&(message.last().get(0)));
incardon's avatar
incardon committed
280
					message.last().resize(j);
incardon's avatar
incardon committed
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
				}
			}

			id = 0;
			prc_recv.clear();


#ifdef VERBOSE_TEST
			timer t;
			t.start();
#endif

			vcl.sendrecvMultipleMessages(prc,message,msg_alloc2,&recv_message);

#ifdef VERBOSE_TEST
			t.stop();
			double clk = t.getwct();
incardon's avatar
incardon committed
298
			double clk_max = clk;
incardon's avatar
incardon committed
299

incardon's avatar
incardon committed
300
			size_t size_send_recv = (prc.size() + recv_message.size()) * j;
incardon's avatar
incardon committed
301
302
			vcl.reduce(size_send_recv);
			vcl.reduce(clk);
incardon's avatar
incardon committed
303
			vcl.max(clk_max);
incardon's avatar
incardon committed
304
305
306
			vcl.execute();
			clk /= vcl.getProcessingUnits();

incardon's avatar
incardon committed
307
			if (vcl.getProcessUnitID() == 0)
incardon's avatar
incardon committed
308
				std::cout << "(Random Pattern: ) Buffer size: " << j << "    Bandwidth (Average): " << size_send_recv / vcl.getProcessingUnits() / clk / 1e6 << " MB/s  " << "    Bandwidth (Total): " << size_send_recv / clk / 1e6 <<  " MB/s    Clock: " << clk << "   Clock MAX: " << clk_max << "\n";
incardon's avatar
incardon committed
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
#endif

			// Check the message

			for (size_t i = 0 ; i < recv_message.size() ; i++)
			{
				std::ostringstream msg;
				msg << "Hello from " << prc_recv.get(i) << " to " << vcl.getProcessUnitID();
				std::string str(msg.str());
				BOOST_REQUIRE_EQUAL(std::equal(str.c_str(),str.c_str() + str.size() ,&(recv_message.get(i).get(0))),true);
			}

			// Reply back

			// Create the message

			prc.clear();
			message.clear();
			for (size_t i = 0 ; i < prc_recv.size() ; i++)
			{
				prc.add(prc_recv.get(i));
				message.add();
				std::ostringstream msg;
				msg << "Hey from " << vcl.getProcessUnitID() << " to " << prc_recv.get(i);
				std::string str(msg.str());
				message.last().resize(str.size());
				std::copy(str.c_str(),&(str.c_str())[msg.str().size()],&(message.last().get(0)));
incardon's avatar
incardon committed
336
				message.last().resize(j);
incardon's avatar
incardon committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
			}

			id = 0;
			prc_recv.clear();
			recv_message.clear();
			vcl.sendrecvMultipleMessages(prc,message,msg_alloc2,&recv_message);

			// Check if the received hey message match the original send

			BOOST_REQUIRE_EQUAL(o_send.size(),prc_recv.size());

			for (size_t i = 0 ; i < o_send.size() ; i++)
			{
				size_t j = 0;
				for ( ; j < prc_recv.size() ; j++)
				{
					if (o_send.get(i) == prc_recv.get(j))
					{
						// found the message check it

						std::ostringstream msg;
						msg << "Hey from " << prc_recv.get(i) << " to " << vcl.getProcessUnitID();
						std::string str(msg.str());
						BOOST_REQUIRE_EQUAL(std::equal(str.c_str(),str.c_str() + str.size() ,&(recv_message.get(i).get(0))),true);
						break;
					}
				}
				// Check that we find always a match
				BOOST_REQUIRE_EQUAL(j != prc_recv.size(),true);
			}
		}
incardon's avatar
incardon committed
368
369
370
371
372
373
374

		// Check long communication pattern

		for (size_t j = 32 ; j < N_LOOP ; j*=2)
		{
			global_step = j;
			// Processor step
incardon's avatar
incardon committed
375
			long int ps = n_proc / (8 + 1);
incardon's avatar
incardon committed
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

			// send message
			openfpm::vector<openfpm::vector<unsigned char>> message;
			// recv message
			openfpm::vector<openfpm::vector<unsigned char>> recv_message(n_proc);

			openfpm::vector<size_t> prc;

			for (size_t i = 0 ; i < 8  && i < n_proc ; i++)
			{
				size_t p_id = ((i+1) * ps + vcl.getProcessUnitID()) % n_proc;
				if (p_id != vcl.getProcessUnitID())
				{
					prc.add(p_id);
					message.add();
					std::ostringstream msg;
					msg << "Hello from " << vcl.getProcessUnitID() << " to " << p_id;
					std::string str(msg.str());
					message.last().resize(j);
					memset(message.last().getPointer(),0,j);
					std::copy(str.c_str(),&(str.c_str())[msg.str().size()],&(message.last().get(0)));
				}
			}

incardon's avatar
incardon committed
400
			recv_message.resize(n_proc);
incardon's avatar
incardon committed
401
402
403
			// The pattern is not really random preallocate the receive buffer
			for (size_t i = 0 ; i < 8  && i < n_proc ; i++)
			{
404
				long int p_id = (- (i+1) * ps + (long int)vcl.getProcessUnitID());
incardon's avatar
incardon committed
405
406
407
408
409
				if (p_id < 0)
					p_id += n_proc;
				else
					p_id = p_id % n_proc;

410
				if (p_id != (long int)vcl.getProcessUnitID())
incardon's avatar
incardon committed
411
					recv_message.get(p_id).resize(j);
incardon's avatar
incardon committed
412
413
			}

incardon's avatar
incardon committed
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
#ifdef VERBOSE_TEST
			timer t;
			t.start();
#endif

			vcl.sendrecvMultipleMessages(prc,message,msg_alloc,&recv_message);

#ifdef VERBOSE_TEST
			t.stop();
			double clk = t.getwct();
			double clk_max = clk;

			size_t size_send_recv = 2 * j * (prc.size());
			vcl.reduce(size_send_recv);
			vcl.max(clk_max);
			vcl.execute();

			if (vcl.getProcessUnitID() == 0)
				std::cout << "(Long pattern: )Buffer size: " << j << "    Bandwidth (Average): " << size_send_recv / vcl.getProcessingUnits() / clk / 1e6 << " MB/s  " << "    Bandwidth (Total): " << size_send_recv / clk / 1e6 << " MB/s    Clock: " << clk << "   Clock MAX: " << clk_max <<"\n";
#endif

			// Check the message
436
			for (long int i = 0 ; i < 8  && i < (long int)n_proc ; i++)
incardon's avatar
incardon committed
437
			{
438
				long int p_id = (- (i+1) * ps + (long int)vcl.getProcessUnitID());
incardon's avatar
incardon committed
439
440
441
442
443
				if (p_id < 0)
					p_id += n_proc;
				else
					p_id = p_id % n_proc;

444
				if (p_id != (long int)vcl.getProcessUnitID())
incardon's avatar
incardon committed
445
446
447
448
449
450
451
452
453
454
455
456
				{
					std::ostringstream msg;
					msg << "Hello from " << p_id << " to " << vcl.getProcessUnitID();
					std::string str(msg.str());
					BOOST_REQUIRE_EQUAL(std::equal(str.c_str(),str.c_str() + str.size() ,&(recv_message.get(p_id).get(0))),true);
				}
				else
				{
					BOOST_REQUIRE_EQUAL(0,recv_message.get(p_id).size());
				}
			}
		}
incardon's avatar
incardon committed
457
458
459
460
461
462
463
464
465
	}

	std::cout << "VCluster unit test stop" << "\n";
}

BOOST_AUTO_TEST_SUITE_END()


#endif /* VCLUSTER_UNIT_TESTS_HPP_ */