VCluster_unit_tests.hpp 12.6 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 128/*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
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
				recv_message.get(p_id).resize(j);
incardon's avatar
incardon committed
197
198
			}

incardon's avatar
incardon committed
199
200
201
202
203
#ifdef VERBOSE_TEST
			timer t;
			t.start();
#endif

204
			recv_message.resize(n_proc);
incardon's avatar
incardon committed
205
206
207
208
209
			vcl.sendrecvMultipleMessages(prc,message,msg_alloc,&recv_message);

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

incardon's avatar
incardon committed
212
			size_t size_send_recv = 2 * j * (prc.size());
incardon's avatar
incardon committed
213
			vcl.reduce(size_send_recv);
incardon's avatar
incardon committed
214
			vcl.max(clk_max);
incardon's avatar
incardon committed
215
216
			vcl.execute();

incardon's avatar
incardon committed
217
			if (vcl.getProcessUnitID() == 0)
incardon's avatar
incardon committed
218
				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
219
220
221
#endif

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

				if (p_id != vcl.getProcessUnitID())
incardon's avatar
incardon committed
231
232
				{
					std::ostringstream msg;
233
					msg << "Hello from " << p_id << " to " << vcl.getProcessUnitID();
incardon's avatar
incardon committed
234
					std::string str(msg.str());
235
					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
236
237
238
				}
				else
				{
239
					BOOST_REQUIRE_EQUAL(0,recv_message.get(p_id).size());
incardon's avatar
incardon committed
240
241
242
243
244
245
				}
			}
		}

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

incardon's avatar
incardon committed
248
		// Check random pattern (maximum 16 processors)
incardon's avatar
incardon committed
249

incardon's avatar
incardon committed
250
		for (size_t j = 32 ; j < N_LOOP && n_proc < 16 ; j*=2)
incardon's avatar
incardon committed
251
252
253
254
255
256
257
258
259
260
261
262
263
264
		{
			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
265
				if (d(eg) == 0)
incardon's avatar
incardon committed
266
267
268
269
270
271
272
273
274
				{
					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
275
					message.last().resize(j);
incardon's avatar
incardon committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
				}
			}

			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
293
			double clk_max = clk;
incardon's avatar
incardon committed
294

incardon's avatar
incardon committed
295
			size_t size_send_recv = (prc.size() + recv_message.size()) * j;
incardon's avatar
incardon committed
296
297
			vcl.reduce(size_send_recv);
			vcl.reduce(clk);
incardon's avatar
incardon committed
298
			vcl.max(clk_max);
incardon's avatar
incardon committed
299
300
301
			vcl.execute();
			clk /= vcl.getProcessingUnits();

incardon's avatar
incardon committed
302
			if (vcl.getProcessUnitID() == 0)
incardon's avatar
incardon committed
303
				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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#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
331
				message.last().resize(j);
incardon's avatar
incardon committed
332
333
334
335
336
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
			}

			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
363
364
365
366
367
368
369

		// Check long communication pattern

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

			// 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
395
396
397
398
			// 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 = (- (i+1) * ps + (long int)vcl.getProcessUnitID()) % n_proc;
incardon's avatar
incardon committed
399
				recv_message.get(p_id).resize(j);
incardon's avatar
incardon committed
400
401
			}

incardon's avatar
incardon committed
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
#ifdef VERBOSE_TEST
			timer t;
			t.start();
#endif

			recv_message.resize(n_proc);
			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
incardon's avatar
incardon committed
425
			for (long int i = 0 ; i < 8  && i < n_proc ; i++)
incardon's avatar
incardon committed
426
			{
incardon's avatar
incardon committed
427
				long int p_id = (- (i+1) * ps + (long int)vcl.getProcessUnitID()) % n_proc;
incardon's avatar
incardon committed
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
				if (p_id < 0)
					p_id += n_proc;
				else
					p_id = p_id % n_proc;

				if (p_id != vcl.getProcessUnitID())
				{
					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
446
447
448
449
450
451
452
453
454
	}

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

BOOST_AUTO_TEST_SUITE_END()


#endif /* VCLUSTER_UNIT_TESTS_HPP_ */