Blame view

src/split.c 77.6 KB
94b2b13d   Pedro Roque   PHACT source
1
2
3
4
/*
 * split.c
 *
 *  Created on: 19/02/2015
4d26a735   Pedro Roque   Increased recogni...
5
 *      Author: pedro
94b2b13d   Pedro Roque   PHACT source
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 */

#include "split.h"

#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#include "utils\pthread_win32\pthread.h"
#include "windows.h"
#else
#include <pthread.h>
#include <sys/time.h>
#endif

#include "bitmaps.h"
#include "config.h"
#include "config_device.h"
#include "constraints.h"
#include "domains.h"
#include "intervals.h"
#include "solve.h"
#include "utils/benchmark.h"
4d26a735   Pedro Roque   Increased recogni...
34
#include "utils/cl_errors.h"
94b2b13d   Pedro Roque   PHACT source
35
36
37
38
39
40
#include "variables.h"

unsigned int devs_working;	// number of devices still working
unsigned int devs_ranked;	// number of devices already ranked
pthread_mutex_t opt_lock;	// to synchronize threads for gathering optimization results
pthread_mutex_t stats_lock;	// to synchronize threads for gathering statistics results
4d26a735   Pedro Roque   Increased recogni...
41
42
43
44
45
46
47
48
49
50
pthread_barrier_t barrier;
unsigned int mult_max; 		// ID of the variable that should be expanded when multiplying the ss
unsigned int best_sols_found;	// counter for number of best solutions found
unsigned int vs_labeled_at_exp;	// number of variables marked for labeling that were fully expanded when creating sub-search spaces
bool filtering = false;
bool all_GPUs = true;

/*
 * Split the CSP between all the selected devices and work-items and solves it.
 * If only one solution, or the best solution is wanted it return 1 if it is found, or 0 if none is found.
94b2b13d   Pedro Roque   PHACT source
51
52
53
54
55
56
57
58
 * If all solutions must be found it returns the number of solutions found.
 * */
cl_ulong solve_CSP() {

	unsigned int i, j;

	if (N_VS_ORIGINAL == 0) {
		N_VS_ORIGINAL = V_ID_CNTR;
4d26a735   Pedro Roque   Increased recogni...
59
	}
94b2b13d   Pedro Roque   PHACT source
60
	if (N_CS_ORIGINAL == 0) {
4d26a735   Pedro Roque   Increased recogni...
61
62
		N_CS_ORIGINAL = C_ID_CNTR;
	}
94b2b13d   Pedro Roque   PHACT source
63

94b2b13d   Pedro Roque   PHACT source
64
	if (PRINT_CSP) {
94b2b13d   Pedro Roque   PHACT source
65
		print_CSP();
4d26a735   Pedro Roque   Increased recogni...
66
67
	}

94b2b13d   Pedro Roque   PHACT source
68
	if (N_DEVS > 1 && DOMAIN_TYPE == INTERVAL) {
4d26a735   Pedro Roque   Increased recogni...
69
		fprintf(stderr, "\nPHACT cannot use interval domains with more than one device at the same time.\n"
94b2b13d   Pedro Roque   PHACT source
70
				"Please remove \"-INTERVALS\" from the command arguments, or use a single device.\n\n");
4d26a735   Pedro Roque   Increased recogni...
71
72
		exit(-1);
	}
94b2b13d   Pedro Roque   PHACT source
73

4d26a735   Pedro Roque   Increased recogni...
74
75
76
	if (CS_IGNORE && DOMAIN_TYPE == INTERVAL) {
		CS_IGNORE = false;
	}
94b2b13d   Pedro Roque   PHACT source
77

4d26a735   Pedro Roque   Increased recogni...
78
#if PRE_FILTER
94b2b13d   Pedro Roque   PHACT source
79
80
	// Prunes domain values that are already inconsistent at CSP definition
	if (!filter_CSP()) {
4d26a735   Pedro Roque   Increased recogni...
81
		return 0;
94b2b13d   Pedro Roque   PHACT source
82
	}
4d26a735   Pedro Roque   Increased recogni...
83

94b2b13d   Pedro Roque   PHACT source
84
	// If these results are a solution, returns 1
4d26a735   Pedro Roque   Increased recogni...
85
86
87
88
89
90
	if (cs_check(false)) {
		return 1;
	}

	// remove constraints fixed after filtering
	if (CS_IGNORE) {
94b2b13d   Pedro Roque   PHACT source
91
		cs_remove_ignored();
4d26a735   Pedro Roque   Increased recogni...
92
93
94
	}

	// all the constraints were fixed at filtering, but some variables are not singleton
94b2b13d   Pedro Roque   PHACT source
95
	if (N_CS == 0) {
4d26a735   Pedro Roque   Increased recogni...
96
97
98
		j = 1;
		for (i = 0; i < N_VS; i++) {
			j *= VS[i].n_vals;
94b2b13d   Pedro Roque   PHACT source
99
		}
4d26a735   Pedro Roque   Increased recogni...
100
101
102
103

		printf("\n");

		return j;
94b2b13d   Pedro Roque   PHACT source
104
	}
4d26a735   Pedro Roque   Increased recogni...
105
106
#endif

94b2b13d   Pedro Roque   PHACT source
107
	devs_ranked = 0;	// number of devices already ranked
4d26a735   Pedro Roque   Increased recogni...
108
109
110
	mult_max = 1; 	// ID of the variable that should be expanded when multiplying the ss
	best_sols_found = 1;	// counter for number of best solutions found
	vs_labeled_at_exp = 0;	// number of variables marked for labeling that were fully expanded when creating sub-search spaces
94b2b13d   Pedro Roque   PHACT source
111
	unsigned int n_ss = 0;		// Number of sub-search spaces created
4d26a735   Pedro Roque   Increased recogni...
112
113
114
115
116
117
	unsigned int depth = 0;		// Tree expansion depth needed to get n_ss disjoint search spaces
	unsigned int gpu_cntr = 0;	// Number of GPUs compatible with OpenCL present on the running machine
	unsigned int cpu_cntr = 0;	// Number of CPUs compatible with OpenCL present on the running machine
	unsigned int acc_cntr = 0;	// Number of ACCs compatible with OpenCL present on the running machine
	cl_ulong result = 0;	// Number of solutions found, or 0 or 1 if only one solution is wanted
	unsigned int next_str = 0;	// Index in stores where the next unexplored sub-search space is placed (atomic read and write)
94b2b13d   Pedro Roque   PHACT source
118
	unsigned char sol_found = 0;	// To set to 1 when only one solution is wanted and is found (atomic read and write)
4d26a735   Pedro Roque   Increased recogni...
119
120
121
122
	int thread_ret;			// Value returned from each device thread
	unsigned int n_vs_cs;	// number of all variables in all constraints
	unsigned int n_cs_vs;	// number of all constraints in all variables
	unsigned int n_const_cs;	// number of all constant values in all constraints with more than one constant value
94b2b13d   Pedro Roque   PHACT source
123
	size_t l_mem_per_wi;	// size in bytes of the local memory needed per work-item
4d26a735   Pedro Roque   Increased recogni...
124
125
126
	char* host_name = NULL;

	STATS.n_solutions = 0;
94b2b13d   Pedro Roque   PHACT source
127
	STATS.search_spaces = 0;
4d26a735   Pedro Roque   Increased recogni...
128
129
130
131
132
133

	platf_args* platform_args;		// each platform arguments for all devices of the same platform
	cl_device_id gpu_dev[MAX_DEVS];		// to save all GPUs cl_device_id
	cl_platform_id gpu_platf[MAX_DEVS];	// to save all GPUs cl_platform_id
	cl_device_id cpu_dev[MAX_DEVS];		// to save all CPUs cl_device_id
	cl_platform_id cpu_platf[MAX_DEVS];	// to save all CPUs cl_platform_id
94b2b13d   Pedro Roque   PHACT source
134
	cl_device_id acc_dev[MAX_DEVS];		// to save all ACCs cl_device_id
4d26a735   Pedro Roque   Increased recogni...
135
136
137
138
	cl_platform_id acc_platf[MAX_DEVS];	// to save all ACCs cl_platform_id
	cl_platform_id* platfs = NULL;		// to save all devices cl_platform_id
	cl_device_id* devs = NULL;		// to save all devices cl_device_id
	cl_uint platf_cnt = 0;			// number of platforms (Intel, Nvidia...)
94b2b13d   Pedro Roque   PHACT source
139
	cl_uint dev_cnt = 0;			// number of devices on each platform (CPU, MIC...)
94b2b13d   Pedro Roque   PHACT source
140
	cl_int ret;		// output of clGetPlatformIDs and clGetDeviceIDs
4d26a735   Pedro Roque   Increased recogni...
141
	size_t val_size;
94b2b13d   Pedro Roque   PHACT source
142

4d26a735   Pedro Roque   Increased recogni...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	// Use command line heuristics for labeling and assignment, if existent
	// if not use default
	if (LABEL_MODE_COM != DEFAULT_L) {
		LABEL_MODE = LABEL_MODE_COM;

	} else if (LABEL_MODE == DEFAULT_L) {
		LABEL_MODE = LABEL_MODE_D;
	}
	if (ASSIGN_MODE_COM != DEFAULT_A) {
		ASSIGN_MODE = ASSIGN_MODE_COM;

	} else if (ASSIGN_MODE == DEFAULT_A) {
		ASSIGN_MODE = ASSIGN_MODE_D;
	}

	init_csp_and_d_bits();

	// discover all platforms (Intel, Nvidia, AMD,...)
	ret = clGetPlatformIDs(0, NULL, &platf_cnt);
	cl_check_error(ret, "clGetPlatformIDs", "discovering devices");
	platfs = (cl_platform_id*) malloc(platf_cnt * sizeof(cl_platform_id));
	ret = clGetPlatformIDs(platf_cnt, platfs, NULL);
	cl_check_error(ret, "clGetPlatformIDs", "discovering devices");

	platform_args = (platf_args*) malloc(platf_cnt * sizeof(platf_args));

	// when all devices should be used
	if (ALL_DEVS) {
		N_DEVS = 0;
		// for each platform
		for (i = 0; i < platf_cnt; i++) {
			// discover all devices (GPUs, CPUs, MICs,...)
			ret = clGetDeviceIDs(platfs[i], CL_DEVICE_TYPE_ALL, 0, NULL, &dev_cnt);
			cl_check_error(ret, "clGetDeviceIDs", "discovering devices");
			devs = (cl_device_id*) malloc(sizeof(cl_device_id) * dev_cnt);
			ret = clGetDeviceIDs(platfs[i], CL_DEVICE_TYPE_ALL, dev_cnt, devs, NULL);
			cl_check_error(ret, "clGetDeviceIDs", "discovering devices");

			platform_args[i].platform_id = platfs[i];
			platform_args[i].n_devs = dev_cnt;

			// for each device
			for (j = 0; j < dev_cnt; j++) {
				// Identify the type of device (GPU, CPU, MIC,...)
				cl_device_type cl_device_type;
94b2b13d   Pedro Roque   PHACT source
188

4d26a735   Pedro Roque   Increased recogni...
189
190
191
				ret = clGetDeviceInfo(devs[j], CL_DEVICE_TYPE, sizeof(cl_device_type), &cl_device_type, NULL);
				cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_TYPE");

94b2b13d   Pedro Roque   PHACT source
192
				// to identify the device that user wants to use
4d26a735   Pedro Roque   Increased recogni...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
				if (cl_device_type & CL_DEVICE_TYPE_GPU) {
					DEVICES_INFO[N_DEVS].type = CL_DEVICE_TYPE_GPU;
					DEVICES_INFO[N_DEVS].dev_type_n = (int)gpu_cntr + 1;
					DEVICES_INFO[N_DEVS].n_wg = 0;
					DEVICES_INFO[N_DEVS].n_wi_wg = 0;
					gpu_platf[gpu_cntr] = platfs[i];
					gpu_dev[gpu_cntr++] = devs[j];
				} else if (cl_device_type & CL_DEVICE_TYPE_CPU) {
					DEVICES_INFO[N_DEVS].type = CL_DEVICE_TYPE_CPU;
					DEVICES_INFO[N_DEVS].dev_type_n = (int)cpu_cntr + 1;
					DEVICES_INFO[N_DEVS].n_wg = 0;
					DEVICES_INFO[N_DEVS].n_wi_wg = 0;
					cpu_platf[cpu_cntr] = platfs[i];
					cpu_dev[cpu_cntr++] = devs[j];

					// get device name
					ret = clGetDeviceInfo(devs[j], CL_DEVICE_NAME, 0, NULL, &val_size);
					cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
					char* aux_name = (char*) malloc(val_size);
					ret = clGetDeviceInfo(devs[j], CL_DEVICE_NAME, val_size, aux_name, NULL);
					cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");

					// trim leading spaces on device name
					unsigned int del = 0;
					while (isspace((unsigned char )(aux_name[del])))
						del++;
					host_name =  (char*) malloc(val_size - del);
					strcpy(host_name, &aux_name[del]);
					free(aux_name);

				} else if (cl_device_type & CL_DEVICE_TYPE_ACCELERATOR) {
					DEVICES_INFO[N_DEVS].type = CL_DEVICE_TYPE_ACCELERATOR;
					DEVICES_INFO[N_DEVS].dev_type_n = (int)acc_cntr + 1;
					DEVICES_INFO[N_DEVS].n_wg = 0;
					DEVICES_INFO[N_DEVS].n_wi_wg = 0;
					acc_platf[acc_cntr] = platfs[i];
					acc_dev[acc_cntr++] = devs[j];
				} else {
					fprintf(stderr, "\nclGetDeviceInfo returned a device type that is not supported by the Solver.\n");
					exit(-1);
				}
				N_DEVS++;
			}
		}
		// when user selected the devices to use
	} else {
		// for each platform
		for (i = 0; i < platf_cnt; i++) {

			// discover all devices (GPUs, CPUs, MICs,...)
			ret = clGetDeviceIDs(platfs[i], CL_DEVICE_TYPE_ALL, 0, NULL, &dev_cnt);
			cl_check_error(ret, "clGetDeviceIDs", "discovering devices");
			devs = (cl_device_id*) malloc(dev_cnt * sizeof(cl_device_id));
			ret = clGetDeviceIDs(platfs[i], CL_DEVICE_TYPE_ALL, dev_cnt, devs, NULL);
			cl_check_error(ret, "clGetDeviceIDs", "discovering devices");

			platform_args[i].platform_id = platfs[i];
			platform_args[i].n_devs = dev_cnt;

			// for each device
			for (j = 0; j < dev_cnt; j++) {
				// Identify the type of device (GPU, CPU, MIC,...)
				cl_device_type cl_device_type;
				ret = clGetDeviceInfo(devs[j], CL_DEVICE_TYPE, sizeof(cl_device_type), &cl_device_type, NULL);
				cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_TYPE");

				// to identify the device that user wants to use
				if (cl_device_type & CL_DEVICE_TYPE_GPU) {
					gpu_platf[gpu_cntr] = platfs[i];
					gpu_dev[gpu_cntr++] = devs[j];
				} else if (cl_device_type & CL_DEVICE_TYPE_CPU) {
					cpu_platf[cpu_cntr] = platfs[i];
					cpu_dev[cpu_cntr++] = devs[j];

94b2b13d   Pedro Roque   PHACT source
267
					// get device name
4d26a735   Pedro Roque   Increased recogni...
268
269
270
271
					ret = clGetDeviceInfo(devs[j], CL_DEVICE_NAME, 0, NULL, &val_size);
					cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
					char* aux_name = (char*) malloc(val_size);
					ret = clGetDeviceInfo(devs[j], CL_DEVICE_NAME, val_size, aux_name, NULL);
94b2b13d   Pedro Roque   PHACT source
272
					cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
4d26a735   Pedro Roque   Increased recogni...
273
274

					// trim leading spaces on device name
94b2b13d   Pedro Roque   PHACT source
275
276
					unsigned int del = 0;
					while (isspace((unsigned char )(aux_name[del])))
4d26a735   Pedro Roque   Increased recogni...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
						del++;
					host_name =  (char*) malloc(val_size - del);
					strcpy(host_name, &aux_name[del]);
					free(aux_name);

				} else if (cl_device_type & CL_DEVICE_TYPE_ACCELERATOR) {
					acc_platf[acc_cntr] = platfs[i];
					acc_dev[acc_cntr++] = devs[j];
				} else {
					fprintf(stderr, "\nclGetDeviceInfo returned a device type that is not supported by the Solver.\n");
					exit(-1);
				}
			}
			free(devs);
		}
	}
	free(platfs);

	if (N_GPUs > gpu_cntr || N_CPUs > cpu_cntr || N_ACCs > acc_cntr) {
		fprintf(stderr, "\nYou are trying to use a device that is not compatible with OpenCL, or that doesn't exist on this machine. "
				"Please check the selected devices.\n");
		exit(-1);
	}

	for (i = 0; i < N_DEVS; i++) {
		// if user wants to use all the devices of a type
		if (DEVICES_INFO[i].dev_type_n == 0) {
			DEVICES_INFO[i].dev_type_n = 1;

			if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_GPU) {
				for (j = 1; j < gpu_cntr; j++) {
					DEVICES_INFO[N_DEVS].dev_type_n = DEVICES_INFO[i].dev_type_n + (int)j;
					DEVICES_INFO[N_DEVS].type = DEVICES_INFO[i].type;
					DEVICES_INFO[N_DEVS].n_wg = DEVICES_INFO[i].n_wg;
					DEVICES_INFO[N_DEVS].n_wi_wg = DEVICES_INFO[i].n_wi_wg;
					N_DEVS++;
				}
			} else if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_CPU) {
				for (j = 1; j < cpu_cntr; j++) {
					DEVICES_INFO[N_DEVS].dev_type_n = DEVICES_INFO[i].dev_type_n + (int)j;
					DEVICES_INFO[N_DEVS].type = DEVICES_INFO[i].type;
					DEVICES_INFO[N_DEVS].n_wg = DEVICES_INFO[i].n_wg;
					DEVICES_INFO[N_DEVS].n_wi_wg = DEVICES_INFO[i].n_wi_wg;
					N_DEVS++;
				}

				all_GPUs = false;

			} else {
				for (j = 1; j < acc_cntr; j++) {
					DEVICES_INFO[N_DEVS].dev_type_n = DEVICES_INFO[i].dev_type_n + (int)j;
94b2b13d   Pedro Roque   PHACT source
328
					DEVICES_INFO[N_DEVS].type = DEVICES_INFO[i].type;
4d26a735   Pedro Roque   Increased recogni...
329
330
331
332
333
334
335
336
337
					DEVICES_INFO[N_DEVS].n_wg = DEVICES_INFO[i].n_wg;
					DEVICES_INFO[N_DEVS].n_wi_wg = DEVICES_INFO[i].n_wi_wg;
					N_DEVS++;
				}

				all_GPUs = false;
			}
		}

94b2b13d   Pedro Roque   PHACT source
338
339
		// save the platform_id, device_id and the n_wi_wg (if default) for all the devices to use
		if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_GPU) {
4d26a735   Pedro Roque   Increased recogni...
340
			DEVICES_INFO[i].platform_id = gpu_platf[DEVICES_INFO[i].dev_type_n - 1];
94b2b13d   Pedro Roque   PHACT source
341
			DEVICES_INFO[i].device_id = gpu_dev[DEVICES_INFO[i].dev_type_n - 1];
4d26a735   Pedro Roque   Increased recogni...
342
343
344

		} else if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_CPU) {
			DEVICES_INFO[i].platform_id = cpu_platf[DEVICES_INFO[i].dev_type_n - 1];
94b2b13d   Pedro Roque   PHACT source
345
			DEVICES_INFO[i].device_id = cpu_dev[DEVICES_INFO[i].dev_type_n - 1];
4d26a735   Pedro Roque   Increased recogni...
346
347
348
349
350
351
		} else {
			DEVICES_INFO[i].platform_id = acc_platf[DEVICES_INFO[i].dev_type_n - 1];
			DEVICES_INFO[i].device_id = acc_dev[DEVICES_INFO[i].dev_type_n - 1];
		}

		// get number of compute units on this device
94b2b13d   Pedro Roque   PHACT source
352
353
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &DEVICES_INFO[i].compute_units, NULL);
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_MAX_COMPUTE_UNITS");
4d26a735   Pedro Roque   Increased recogni...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
		// get maximum cores frequency
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(cl_uint), &DEVICES_INFO[i].max_freq, NULL);
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_MAX_CLOCK_FREQUENCY");

		// get the amount of local memory to check if it is enough
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(DEVICES_INFO[i].local_mem_max_alloc),
				&DEVICES_INFO[i].local_mem_max_alloc, NULL);
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_LOCAL_MEM_SIZE");

		// set number of work-items and work-groups to use on each device
		if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_GPU) {
				DEVICES_INFO[i].use_local_mem = false;
				DEVICES_INFO[i].def_n_wi_wg = GPU_DEFAULT_N_WI;
				DEVICES_INFO[i].def_n_wg = GPU_DEFAULT_N_WG;

		} else if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_CPU) {
			DEVICES_INFO[i].use_local_mem = true;
			DEVICES_INFO[i].def_n_wi_wg = 1;	// default number of work-items per work-group to use
			DEVICES_INFO[i].def_n_wg = DEVICES_INFO[i].compute_units;	// default number of work-groups to use

		} // MICs
94b2b13d   Pedro Roque   PHACT source
375
		else {
4d26a735   Pedro Roque   Increased recogni...
376
			DEVICES_INFO[i].use_local_mem = true;
94b2b13d   Pedro Roque   PHACT source
377
			DEVICES_INFO[i].def_n_wi_wg = 1;	// default number of work-items per work-group to use
4d26a735   Pedro Roque   Increased recogni...
378
379
380
381
382
383
384
385
			DEVICES_INFO[i].def_n_wg = DEVICES_INFO[i].compute_units;	// default number of work-groups to use
		}

		if (DEVICES_INFO[i].n_wg == 0) {
			DEVICES_INFO[i].n_wg = DEVICES_INFO[i].def_n_wg;
		}
		if (DEVICES_INFO[i].n_wi_wg == 0) {
			DEVICES_INFO[i].n_wi_wg = DEVICES_INFO[i].def_n_wi_wg;
94b2b13d   Pedro Roque   PHACT source
386
		}
4d26a735   Pedro Roque   Increased recogni...
387
388
389

		DEVICES_INFO[i].stores_explored = 0;
		DEVICES_INFO[i].last_1ss_solv_time = 0;
94b2b13d   Pedro Roque   PHACT source
390
		DEVICES_INFO[i].avg_1ss_solv_time = 0;
4d26a735   Pedro Roque   Increased recogni...
391
392
393
394
		DEVICES_INFO[i].max_1ss_solv_time = 0;
		DEVICES_INFO[i].n_ss_mult = 1;
		DEVICES_INFO[i].rank = 0;
		DEVICES_INFO[i].times_used = 0;
94b2b13d   Pedro Roque   PHACT source
395
		DEVICES_INFO[i].ms_solve_time = 0;
4d26a735   Pedro Roque   Increased recogni...
396
397
398
399
400
401
402
		DEVICES_INFO[i].first_time_ranked = false;
		DEVICES_INFO[i].props_total = 0;
		DEVICES_INFO[i].last_props = 0;
		DEVICES_INFO[i].avg_time_prop = 0;
		DEVICES_INFO[i].last_time_prop = 0;
		DEVICES_INFO[i].max_time_prop = 0;
		DEVICES_INFO[i].ranked = false;
94b2b13d   Pedro Roque   PHACT source
403
		DEVICES_INFO[i].working = true;
4d26a735   Pedro Roque   Increased recogni...
404
405
406
407
408
409
		DEVICES_INFO[i].last_explor_time = 0;
		DEVICES_INFO[i].n_fast_blocks = 0;
		DEVICES_INFO[i].sols_found = 0;
		DEVICES_INFO[i].n_buffers = 1;
		DEVICES_ARGS[i].split_values_ext = 1;
		DEVICES_INFO[i].exp_values = calloc(N_VS, sizeof(unsigned int));
94b2b13d   Pedro Roque   PHACT source
410
		DEVICES_INFO[i].n_empty_blocks = 0;
4d26a735   Pedro Roque   Increased recogni...
411
412
413
414
	}

	if (DOMAIN_TYPE == INTERVAL && !CAN_USE_INTERVALS) {
		fprintf(stderr, "\nThe domains of the variables of the current CSP contain non-contiguous values,\n"
94b2b13d   Pedro Roque   PHACT source
415
				"which are not permitted when using interval domains in PHACT.\n"
4d26a735   Pedro Roque   Increased recogni...
416
417
418
419
420
				"Please remove \"-INTERVALS\" from the command arguments.\n\n");
		exit(-1);
	}

	// if using intervals convert bitmaps to intervals
94b2b13d   Pedro Roque   PHACT source
421
	if (DOMAIN_TYPE == INTERVAL) {
4d26a735   Pedro Roque   Increased recogni...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
		set_interval_domains();
	}

	// Reset variables set for labeling, because some of them may be singleton already and count the number of variables that should be labeled
	N_VS_TO_LABEL = vs_cnt_vs_to_label(VS, N_VS);

	n_vs_cs = (unsigned int)cs_cnt_vs(CS, N_CS);	// count the number of variables in all constraints
	n_cs_vs = vs_cnt_cs(VS, N_VS);	// count the number of constraints in all variables
	n_const_cs = (unsigned int)cs_cnt_constants(CS, N_CS);	// count the number of constants constrained by all the constraints (if more than one)

	if (ASSIGN_MODE == SPLIT_VALS) {
		unsigned int split_values_ext = 1;
		unsigned int n_vals_ctr = 1;
		for (i = 0; i < N_VS; i++) {
94b2b13d   Pedro Roque   PHACT source
436
			if (VS[i].to_label && VS[i].n_vals > n_vals_ctr) {
4d26a735   Pedro Roque   Increased recogni...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
				n_vals_ctr = VS[i].n_vals;
			}
		}
		while (((unsigned int)(n_vals_ctr / 2)) > 0) {
			n_vals_ctr /= 2;
			split_values_ext++;
		}
		for (i = 0; i < N_DEVS; i++) {
			DEVICES_ARGS[i].split_values_ext = split_values_ext;
		}
	}

#if SORT_BY_LABEL
	// sort variables by the ones that may be labeled
	vs_sort_label_first(VS, N_VS);

#elif SORT_BY_MOST_USED_CONSTR
	// sort constraints on each variable by the constraint that is more common on the CSP
	vs_sort_constr(VS, N_VS);

#elif SORT_BY_LABEL_MORE_VALS
	// sort variables by the ones that may be labeled and that have more values on their domains
	vs_sort_label_more_vals_first();

#elif SORT_BY_LABEL_LESS_VALS
	// sort variables by the ones that may be labeled and that have more values on their domains
	vs_sort_label_less_vals_first();
94b2b13d   Pedro Roque   PHACT source
464
#endif
4d26a735   Pedro Roque   Increased recogni...
465
466
467
468
469
470
471
472
473
474
475
476

	// split the search space and fill the stores
	split_ss(&depth, &n_ss, (unsigned int)N_VS_TO_LABEL);

	if (N_VS_TO_LABEL == 0) {
		fprintf(stderr, "\nNo CSP variable is marked for labeling. Please mark at least one variable for labeling.\n\n");
		exit(-1);
	}

	// variables that are fully expanded during sub-search spaces creation are already labeled
	N_VS_TO_LABEL -= (int)vs_labeled_at_exp;
	if (N_VS_TO_LABEL <= 0) {
94b2b13d   Pedro Roque   PHACT source
477
		N_VS_TO_LABEL = 1;
4d26a735   Pedro Roque   Increased recogni...
478
479
480
481
	}

	if (USE_TTL) {
		fprintf(stderr, "\nTTL is enabled inside the kernel.\n\n");
94b2b13d   Pedro Roque   PHACT source
482
	}
94b2b13d   Pedro Roque   PHACT source
483

4d26a735   Pedro Roque   Increased recogni...
484
485
	if (!QUIET) {
		printf("\nSolving the CSP with:\n - Host: %s", host_name);
94b2b13d   Pedro Roque   PHACT source
486
	}
4d26a735   Pedro Roque   Increased recogni...
487
488
489
	if (VERBOSE) {
		if (DOMAIN_TYPE == BITMAP_) {
			printf(" with %d-bits bitmap domains on %d-bits words\n", H_BITS, H_WORD);
94b2b13d   Pedro Roque   PHACT source
490
		} else if (DOMAIN_TYPE == INTERVAL) {
4d26a735   Pedro Roque   Increased recogni...
491
492
493
494
495
			printf(" with interval domains\n");
		}
	} else if (!QUIET) {
		printf("\n");
	}
94b2b13d   Pedro Roque   PHACT source
496

4d26a735   Pedro Roque   Increased recogni...
497
498
499
500
	// set revision to on (REV=1) or off (REV=0) by default. If PRE_LABELING==2, it is set to 1 if any propagator is capable of propagating
	// variables with more than one value in its domain
	if (PRE_LABELING == 0) {
		REV = 0;
94b2b13d   Pedro Roque   PHACT source
501
502
	} else if (PRE_LABELING == 1) {
		REV = 1;
4d26a735   Pedro Roque   Increased recogni...
503
504
	}
	if (!QUIET) {
94b2b13d   Pedro Roque   PHACT source
505
		printf(" - Device(s) with %s and %s heuristics", get_label_heur(), get_assign_heur());
4d26a735   Pedro Roque   Increased recogni...
506
507
508
	}
	if (REV == 1 && !QUIET) {
		printf(" (and revision)");
94b2b13d   Pedro Roque   PHACT source
509
	}
4d26a735   Pedro Roque   Increased recogni...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
	if (!QUIET) {
		printf(":\n");
	}

	if (host_name != NULL) {
		free(host_name);
	}

	if (DOMAIN_TYPE == BITMAP_) {
		l_mem_per_wi = (N_VS + 2) * sizeof(cl_ushort) + N_VS * (sizeof(cl_var_p_bitmap) - sizeof(cl_bitmap) + DOMAIN_SIZE);
	} else {
		l_mem_per_wi = (N_VS + 2) * sizeof(cl_ushort) + N_VS * sizeof(cl_var_p_interval);
	}

	// check if memory is enough. If not, reduce the number of wi, and wg if also needed.
	for (i = 0; i < N_DEVS; i++) {

#if USE_LOCAL_MEM == 0
94b2b13d   Pedro Roque   PHACT source
528
		DEVICES_INFO[i].use_local_mem = false;
94b2b13d   Pedro Roque   PHACT source
529
#elif USE_LOCAL_MEM == 1
4d26a735   Pedro Roque   Increased recogni...
530
531
532
533
		DEVICES_INFO[i].use_local_mem = true;
#endif

		// get device name
94b2b13d   Pedro Roque   PHACT source
534
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_NAME, 0, NULL, &val_size);
4d26a735   Pedro Roque   Increased recogni...
535
536
537
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
		char* aux_name = (char*) malloc(val_size);
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_NAME, val_size, aux_name, NULL);
94b2b13d   Pedro Roque   PHACT source
538
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
4d26a735   Pedro Roque   Increased recogni...
539
540
541

		// trim leading spaces on device name
		unsigned int del = 0;
94b2b13d   Pedro Roque   PHACT source
542
		while (isspace((unsigned char )(aux_name[del])))
4d26a735   Pedro Roque   Increased recogni...
543
544
545
			del++;
		DEVICES_INFO[i].dev_name = (char*) malloc(val_size - del);
		strcpy(DEVICES_INFO[i].dev_name, &aux_name[del]);
94b2b13d   Pedro Roque   PHACT source
546
		free(aux_name);
4d26a735   Pedro Roque   Increased recogni...
547
548
549
550
551
552

		if (DEVICES_INFO[i].use_local_mem && DEVICES_INFO[i].local_mem_max_alloc < l_mem_per_wi * DEVICES_INFO[i].n_wi_wg) {
			printf("     Due to the amount of memory required, local memory will not be used in %s.\n", DEVICES_INFO[i].dev_name);
			DEVICES_INFO[i].use_local_mem = false;
		}

94b2b13d   Pedro Roque   PHACT source
553
554
		DEVICES_ARGS[i].n_vs_to_label = (unsigned int)N_VS_TO_LABEL;
		DEVICES_ARGS[i].n_vs_cs = n_vs_cs;
4d26a735   Pedro Roque   Increased recogni...
555
		DEVICES_ARGS[i].n_cs_vs = n_cs_vs;
94b2b13d   Pedro Roque   PHACT source
556
		DEVICES_ARGS[i].n_const_cs = n_const_cs;
4d26a735   Pedro Roque   Increased recogni...
557

94b2b13d   Pedro Roque   PHACT source
558
		// get the amount of allowable global memory per buffer to check if it is enough (or if more than one buffer is required)
4d26a735   Pedro Roque   Increased recogni...
559
560
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(DEVICES_INFO[i].global_mem_max_alloc),
				&DEVICES_INFO[i].global_mem_max_alloc, NULL);
94b2b13d   Pedro Roque   PHACT source
561
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_MAX_MEM_ALLOC_SIZE");
4d26a735   Pedro Roque   Increased recogni...
562
563

		// get the size of the global memory
94b2b13d   Pedro Roque   PHACT source
564
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(DEVICES_INFO[i].global_mem_size),
4d26a735   Pedro Roque   Increased recogni...
565
566
567
568
				&DEVICES_INFO[i].global_mem_size, NULL);
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_GLOBAL_MEM_SIZE");

		// get the maximum size of each constant memory buffer to check if it is enough
94b2b13d   Pedro Roque   PHACT source
569
		ret = clGetDeviceInfo(DEVICES_INFO[i].device_id, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(DEVICES_INFO[i].constant_mem_max_alloc),
4d26a735   Pedro Roque   Increased recogni...
570
571
				&DEVICES_INFO[i].constant_mem_max_alloc, NULL);
		cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE");
94b2b13d   Pedro Roque   PHACT source
572

4d26a735   Pedro Roque   Increased recogni...
573
574
575
576
577
		size_t n_wg_init = DEVICES_INFO[i].n_wg;
		size_t n_wi_wg_init = DEVICES_INFO[i].n_wi_wg;

		if (DEVICES_INFO[i].use_local_mem) {
			// set buffers size and check if global memory is enough
94b2b13d   Pedro Roque   PHACT source
578
			DEVICES_INFO[i].n_wi_wg++;
4d26a735   Pedro Roque   Increased recogni...
579
580
581
			do {
				DEVICES_INFO[i].n_wi_wg--;

94b2b13d   Pedro Roque   PHACT source
582
				// number of work-items that will be created on this device
4d26a735   Pedro Roque   Increased recogni...
583
584
585
586
587
588
589
590
591
592
593
594
				DEVICES_ARGS[i].wi_local = DEVICES_INFO[i].n_wi_wg;
				DEVICES_ARGS[i].wi_total = DEVICES_INFO[i].n_wg * DEVICES_INFO[i].n_wi_wg;

				set_buffs_size(&DEVICES_ARGS[i], &DEVICES_INFO[i], filtering);

#if USE_MORE_BUFFERS
			} while (DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P && DEVICES_INFO[i].n_wi_wg > 1);
#else
			} while (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc && DEVICES_INFO[i].n_wi_wg > 1);
#endif

#if USE_MORE_BUFFERS
94b2b13d   Pedro Roque   PHACT source
595
			// if global memory not enough for 1 wi_wg, exit
4d26a735   Pedro Roque   Increased recogni...
596
597
598
599
600
601
602
			if (DEVICES_INFO[i].n_wi_wg == 1 && DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P) {
#else
			// if global memory not enough for 1 wi_wg, exit
			if (DEVICES_INFO[i].n_wi_wg == 1 && DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc) {
#endif
				DEVICES_INFO[i].n_wg++;
				do {
94b2b13d   Pedro Roque   PHACT source
603
					DEVICES_INFO[i].n_wg--;
4d26a735   Pedro Roque   Increased recogni...
604
605
606
607

					// number of work-items that will be created on this device
					DEVICES_ARGS[i].wi_local = DEVICES_INFO[i].n_wi_wg;
					DEVICES_ARGS[i].wi_total = DEVICES_INFO[i].n_wg * DEVICES_INFO[i].n_wi_wg;
94b2b13d   Pedro Roque   PHACT source
608

4d26a735   Pedro Roque   Increased recogni...
609
610
611
					set_buffs_size(&DEVICES_ARGS[i], &DEVICES_INFO[i], filtering);
#if USE_MORE_BUFFERS
				} while (DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P && DEVICES_INFO[i].n_wg > 1);
94b2b13d   Pedro Roque   PHACT source
612
#else
4d26a735   Pedro Roque   Increased recogni...
613
614
615
616
617
618
619
				} while (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc && DEVICES_INFO[i].n_wg > 1);

#endif
			}
		} else {

			DEVICES_INFO[i].n_wg++;
94b2b13d   Pedro Roque   PHACT source
620
			do {
4d26a735   Pedro Roque   Increased recogni...
621
622
623
				DEVICES_INFO[i].n_wg--;

				// number of work-items that will be created on this device
94b2b13d   Pedro Roque   PHACT source
624
				DEVICES_ARGS[i].wi_local = DEVICES_INFO[i].n_wi_wg;
4d26a735   Pedro Roque   Increased recogni...
625
626
627
				DEVICES_ARGS[i].wi_total = DEVICES_INFO[i].n_wg * DEVICES_INFO[i].n_wi_wg;

				set_buffs_size(&DEVICES_ARGS[i], &DEVICES_INFO[i], filtering);
94b2b13d   Pedro Roque   PHACT source
628
			}
4d26a735   Pedro Roque   Increased recogni...
629
630
631
632
633
634
635
636
#if USE_MORE_BUFFERS
			while (DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P && DEVICES_INFO[i].n_wg > 128);
#else
			while (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc && DEVICES_INFO[i].n_wg > 128);
#endif

			if (DEVICES_INFO[i].n_wg <= 128 && DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc) {
				DEVICES_INFO[i].n_wi_wg++;
94b2b13d   Pedro Roque   PHACT source
637
				do {
4d26a735   Pedro Roque   Increased recogni...
638
639
640
641
					DEVICES_INFO[i].n_wi_wg--;

					// number of work-items that will be created on this device
					DEVICES_ARGS[i].wi_local = DEVICES_INFO[i].n_wi_wg;
94b2b13d   Pedro Roque   PHACT source
642
					DEVICES_ARGS[i].wi_total = DEVICES_INFO[i].n_wg * DEVICES_INFO[i].n_wi_wg;
94b2b13d   Pedro Roque   PHACT source
643

4d26a735   Pedro Roque   Increased recogni...
644
645
646
647
648
649
					set_buffs_size(&DEVICES_ARGS[i], &DEVICES_INFO[i], filtering);
				}
#if USE_MORE_BUFFERS
				while (DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P && DEVICES_INFO[i].n_wi_wg > 1);
#else
				while (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc && DEVICES_INFO[i].n_wi_wg > 1);
94b2b13d   Pedro Roque   PHACT source
650
#endif
4d26a735   Pedro Roque   Increased recogni...
651
652
653
654
655
656
657
			}

#if USE_MORE_BUFFERS
			if (DEVICES_INFO[i].n_wg <= 128 && DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P && DEVICES_INFO[i].n_wi_wg == 1) {
#else
			if (DEVICES_INFO[i].n_wg <= 128 && DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc && DEVICES_INFO[i].n_wi_wg == 1) {
#endif
94b2b13d   Pedro Roque   PHACT source
658
				DEVICES_INFO[i].n_wg++;
4d26a735   Pedro Roque   Increased recogni...
659
660
661
				do {
					DEVICES_INFO[i].n_wg--;

94b2b13d   Pedro Roque   PHACT source
662
					// number of work-items that will be created on this device
94b2b13d   Pedro Roque   PHACT source
663
					DEVICES_ARGS[i].wi_local = DEVICES_INFO[i].n_wi_wg;
4d26a735   Pedro Roque   Increased recogni...
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
					DEVICES_ARGS[i].wi_total = DEVICES_INFO[i].n_wg * DEVICES_INFO[i].n_wi_wg;

					set_buffs_size(&DEVICES_ARGS[i], &DEVICES_INFO[i], filtering);
				}
#if USE_MORE_BUFFERS
				while (DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P && DEVICES_INFO[i].n_wg > 1);
#else
				while (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc && DEVICES_INFO[i].n_wg > 1);
#endif
			}
		}

		if (n_wg_init != DEVICES_INFO[i].n_wg) {
			printf("     Due to the amount of memory required, the number of work-groups was reduced in %s.\n", DEVICES_INFO[i].dev_name);
		}

		if (n_wi_wg_init != DEVICES_INFO[i].n_wi_wg) {
			printf("     Due to the amount of memory required, the number of work-items per work-group was reduced in %s.\n", DEVICES_INFO[i].dev_name);
		}

#if USE_MORE_BUFFERS
		// if global memory not enough for 1 wi_wg and 1 wg, exit
		if (DEVICES_INFO[i].global_mem_used > (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P) {
			fprintf(stderr, "\nPHACT is trying to use more global memory (%lu Mb) than the amount available (%f Mb) on %s (%d) with %lu "
					"work-item(s) and %lu work-group(s).\n If possible, please reduce the amount of work-items per work-group to use.",
					DEVICES_INFO[i].global_mem_used / 1000000, (double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P / 1000000, DEVICES_INFO[i].dev_name,
94b2b13d   Pedro Roque   PHACT source
690
691
692
693
694
695
696
697
698
					DEVICES_INFO[i].dev_type_n, DEVICES_INFO[i].n_wg, DEVICES_INFO[i].n_wi_wg);

			exit(-1);
		}
#else
		// if global memory not enough for 1 wi_wg and 1 wg, exit
		if (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc) {
			fprintf(stderr, "\nPHACT is trying to use more global memory (%lu Mb) than the amount available (%lu Mb) on %s (%d) with %lu "
					"work-item(s) and %lu work-group(s).\n If possible, please reduce the amount of work-items per work-group to use.",
4d26a735   Pedro Roque   Increased recogni...
699
					DEVICES_INFO[i].global_mem_used / 1000000, DEVICES_INFO[i].global_mem_max_alloc / 1000000, DEVICES_INFO[i].dev_name,
94b2b13d   Pedro Roque   PHACT source
700
					DEVICES_INFO[i].dev_type_n, DEVICES_INFO[i].n_wg, DEVICES_INFO[i].n_wi_wg);
4d26a735   Pedro Roque   Increased recogni...
701

94b2b13d   Pedro Roque   PHACT source
702
			exit(-1);
4d26a735   Pedro Roque   Increased recogni...
703
		}
94b2b13d   Pedro Roque   PHACT source
704
#endif
94b2b13d   Pedro Roque   PHACT source
705
706

#if USE_MORE_BUFFERS
4d26a735   Pedro Roque   Increased recogni...
707
708
		// calculate the number of buffers that are needed and divide the work-groups and work-items per them
		if (DEVICES_INFO[i].global_mem_used > DEVICES_INFO[i].global_mem_max_alloc) {
94b2b13d   Pedro Roque   PHACT source
709
			DEVICES_INFO[i].n_buffers = (unsigned int)ceil(((double)DEVICES_INFO[i].global_mem_used * 1.0) / (double)DEVICES_INFO[i].global_mem_max_alloc);
4d26a735   Pedro Roque   Increased recogni...
710
711

			// ensures that the buffers are enough
94b2b13d   Pedro Roque   PHACT source
712
			if (DEVICES_INFO[i].n_buffers > DEVICES_INFO[i].global_mem_size / DEVICES_INFO[i].global_mem_max_alloc) {
4d26a735   Pedro Roque   Increased recogni...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
				DEVICES_INFO[i].n_wg--;
			}
			// for less calculations, all buffers must be assigned to the same number of work-groups
			while (DEVICES_INFO[i].n_wg % DEVICES_INFO[i].n_buffers > 0) {
				DEVICES_INFO[i].n_wg--;
			}

			DEVICES_ARGS[i].backtrack_size = (unsigned int)ceil(((double)DEVICES_ARGS[i].backtrack_size * 1.0) / (double)DEVICES_INFO[i].n_buffers);
		}
#endif

		if (!QUIET) {
			printf("   - %s (%d) with %lu work-group(s) and %lu work-items(s) per work-group", DEVICES_INFO[i].dev_name, DEVICES_INFO[i].dev_type_n,
					DEVICES_INFO[i].n_wg, DEVICES_INFO[i].n_wi_wg);
		}

		if (VERBOSE) {
			if (DEVICES_INFO[i].use_local_mem) {
94b2b13d   Pedro Roque   PHACT source
731
732
733
734
735
736
737
738
739
740
741
				printf(", local memory");
			}

#if USE_MORE_BUFFERS
			if ((double)DEVICES_INFO[i].global_mem_used / 1000000.0 > 1.0) {
				printf(", %.02f Mb (%u buffer(s)) of global memory (Max. %.02f Mb) and", (double)DEVICES_INFO[i].global_mem_used / 1000000.0, DEVICES_INFO[i].n_buffers,
						(double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P / 1000000.0);
			} else {
				printf(", %.02f Kb (%u buffer(s)) of global memory (Max. %.02f Mb) and", (double)DEVICES_INFO[i].global_mem_used / 1000.0, DEVICES_INFO[i].n_buffers,
						(double)DEVICES_INFO[i].global_mem_size * USE_MORE_BUFFERS_P / 1000000.0);
			}
4d26a735   Pedro Roque   Increased recogni...
742
#else
94b2b13d   Pedro Roque   PHACT source
743
			if ((double)DEVICES_INFO[i].global_mem_used / 1000000.0 > 1.0) {
4d26a735   Pedro Roque   Increased recogni...
744
				printf(", %.02f Mb of global memory (Max. %.02f Mb) and", (double)DEVICES_INFO[i].global_mem_used / 1000000.0, (double)DEVICES_INFO[i].global_mem_max_alloc / 1000000.0);
94b2b13d   Pedro Roque   PHACT source
745
			} else {
94b2b13d   Pedro Roque   PHACT source
746
				printf(", %.02f Kb of global memory (Max. %.02f Mb) and", (double)DEVICES_INFO[i].global_mem_used / 1000.0, (double)DEVICES_INFO[i].global_mem_max_alloc / 1000000.0);
4d26a735   Pedro Roque   Increased recogni...
747
748
749
750
			}
#endif

			if (DOMAIN_TYPE == BITMAP_) {
94b2b13d   Pedro Roque   PHACT source
751
				printf(" %d-bits bitmap domains on %d-bits words", CL_BITS_, CL_WORD_);
4d26a735   Pedro Roque   Increased recogni...
752
753
754
			} else if (DOMAIN_TYPE == INTERVAL) {
				printf(" interval domains");
			}
94b2b13d   Pedro Roque   PHACT source
755
#if SHARED_SS > 0
4d26a735   Pedro Roque   Increased recogni...
756
757
			printf(" and %d shared sub-search spaces", DEVICES_ARGS[i].n_shared_stores);
#endif
94b2b13d   Pedro Roque   PHACT source
758

4d26a735   Pedro Roque   Increased recogni...
759
		}
94b2b13d   Pedro Roque   PHACT source
760
		if (!QUIET) {
4d26a735   Pedro Roque   Increased recogni...
761
			printf("\n");
94b2b13d   Pedro Roque   PHACT source
762
		}
4d26a735   Pedro Roque   Increased recogni...
763
	}
94b2b13d   Pedro Roque   PHACT source
764
765

	// calculate the expected speed when comparing the hardware of all the used devices
4d26a735   Pedro Roque   Increased recogni...
766
767
768
769
770
771
772
773
	calculate_rel_expect_speed(DEVICES_INFO);

	// set amount of sub-search spaces to send to each device at the beginning
	for (i = 0; i < N_DEVS; i++) {
		DEVICES_INFO[i].n_ss_mult_max = mult_max;

		// set n_ss_mult_max to the device number of cores
		if (mult_max > DEVICES_INFO[i].n_wi_wg * DEVICES_INFO[i].n_wg) {
94b2b13d   Pedro Roque   PHACT source
774
			DEVICES_INFO[i].n_ss_mult_max = (unsigned int)(DEVICES_INFO[i].n_wi_wg * DEVICES_INFO[i].n_wg);
4d26a735   Pedro Roque   Increased recogni...
775
776
777
		}

		if (DEVICES_INFO[i].n_ss_mult_max > DEVICES_INFO[i].compute_units * 32) {
94b2b13d   Pedro Roque   PHACT source
778

4d26a735   Pedro Roque   Increased recogni...
779
780
781
782
783
784
			if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_GPU) {
				DEVICES_INFO[i].n_ss_mult_max = DEVICES_INFO[i].compute_units * 32;

			} else {
				DEVICES_INFO[i].n_ss_mult_max = DEVICES_INFO[i].compute_units;
			}
94b2b13d   Pedro Roque   PHACT source
785
		}
4d26a735   Pedro Roque   Increased recogni...
786
787

		if (N_DEVS == 1) {
94b2b13d   Pedro Roque   PHACT source
788
			DEVICES_INFO[i].block_size = n_ss;
4d26a735   Pedro Roque   Increased recogni...
789
790
791

		} else if (WORK == CNT) {
			DEVICES_INFO[i].block_size = (unsigned int)(n_ss * CNT_INIT_PERC * DEVICES_INFO[i].rel_speed_expect);
94b2b13d   Pedro Roque   PHACT source
792
			// WORK == ONE or OPT
4d26a735   Pedro Roque   Increased recogni...
793
794
		} else {
			DEVICES_INFO[i].block_size = (unsigned int)(n_ss * OPT_ONE_INIT_PERC * DEVICES_INFO[i].rel_speed_expect);
94b2b13d   Pedro Roque   PHACT source
795
796
797
		}

		if (DEVICES_INFO[i].block_size == 0) {
4d26a735   Pedro Roque   Increased recogni...
798
799
800
801
802
803
804
805
806
807
808
809
810
			DEVICES_INFO[i].block_size = 1;
		}

// multiplier for first block of sub-search spaces
#if SS_MULTIPLIER
	if (DEVICES_INFO[i].block_size > 0) {
		//GPU
		if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_GPU && DEVICES_INFO[i].block_size < SS_GPU / (double)(GPU_DEFAULT_N_WI / DEVICES_INFO[i].n_wi_wg)
				/ (GPU_DEFAULT_N_WG / (double)DEVICES_INFO[i].n_wg * 1.0)) {

			DEVICES_INFO[i].n_ss_mult = (unsigned int)(SS_GPU / (GPU_DEFAULT_N_WI / (double)DEVICES_INFO[i].n_wi_wg * 1.0) / (double)(GPU_DEFAULT_N_WG / (double)DEVICES_INFO[i].n_wg * 1.0))
					/ DEVICES_INFO[i].block_size;
		// ACC
94b2b13d   Pedro Roque   PHACT source
811
812
		} else if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_ACCELERATOR && DEVICES_INFO[i].block_size < SS_ACC / (DEVICES_INFO[i].compute_units / (double)DEVICES_INFO[i].n_wg * 1.0)) {
			DEVICES_INFO[i].n_ss_mult = (unsigned int)(SS_ACC / (DEVICES_INFO[i].compute_units / (double)DEVICES_INFO[i].n_wg * 1.0) / DEVICES_INFO[i].block_size);
4d26a735   Pedro Roque   Increased recogni...
813
814
815
816
817
818
819
820
821
822
823
824
825
826
		// CPU
		} else if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_CPU && DEVICES_INFO[i].block_size < SS_CPU * DEVICES_INFO[i].compute_units / (DEVICES_INFO[i].compute_units
				/ (double)DEVICES_INFO[i].n_wg * 1.0)) {
			DEVICES_INFO[i].n_ss_mult = (unsigned int)((SS_CPU * DEVICES_INFO[i].compute_units) / (double)(DEVICES_INFO[i].compute_units / (double)DEVICES_INFO[i].n_wg * 1.0) / DEVICES_INFO[i].block_size);
		}

		if (DEVICES_INFO[i].n_ss_mult > mult_max) {
			DEVICES_INFO[i].n_ss_mult = mult_max;
		} else if (DEVICES_INFO[i].n_ss_mult == 0) {
			DEVICES_INFO[i].n_ss_mult = 1;
		}
	}
#endif

94b2b13d   Pedro Roque   PHACT source
827
828
829
		DEVICES_INFO[i].first_block_size = DEVICES_INFO[i].block_size;

		if (PRINT_SOLUTIONS && DEVICES_INFO[i].n_wi_wg * DEVICES_INFO[i].n_wg > 1) {
4d26a735   Pedro Roque   Increased recogni...
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
			fprintf(stderr, "The solutions will not be printed because one or more devices will be running more than one thread.\n\n");
			PRINT_SOLUTIONS = false;
		}
	}

	if (!QUIET) {
		printf("\nTotal sub-search spaces: %u\n\n", n_ss);
	}

	// create one thread per device to solve different sub-search spaces in parallel
	pthread_t* threads = malloc(N_DEVS * sizeof(pthread_t));
	threads_data* thread_data = malloc(N_DEVS * sizeof(threads_data));
	void* t_result;
	cl_ulong* results = malloc(N_DEVS * sizeof(cl_ulong));

	if (N_DEVS > 1) {
		if (WORK == OPT && pthread_mutex_init(&opt_lock, NULL) != 0) {
			fprintf(stderr, "ERROR: threads opt_lock not created\n");
			exit(-1);
		}
		if (pthread_mutex_init(&stats_lock, NULL) != 0) {
			fprintf(stderr, "ERROR: threads stats_lock not created\n");
94b2b13d   Pedro Roque   PHACT source
852
			exit(-1);
4d26a735   Pedro Roque   Increased recogni...
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
		}
	}

	if (WORK == OPT) {
		VS_LOCK[VAR_ID_TO_OPT].min = VS[VAR_ID_TO_OPT].min;
		VS_LOCK[VAR_ID_TO_OPT].max = VS[VAR_ID_TO_OPT].max;
		VS_LOCK_BEST[VAR_ID_TO_OPT].min = VS[VAR_ID_TO_OPT].min;
		VS_LOCK_BEST[VAR_ID_TO_OPT].max = VS[VAR_ID_TO_OPT].max;
	}

	devs_working = N_DEVS;

	if (N_DEVS > 1) {
		pthread_barrier_init(&barrier, NULL, N_DEVS);
	}

	for (i = 0; i < N_DEVS; i++) {

		thread_data[i].depth = depth;
		thread_data[i].dev_info = DEVICES_INFO;
		thread_data[i].dev_args = DEVICES_ARGS;
		thread_data[i].dev_number = i;
		thread_data[i].next_str = &next_str;
		thread_data[i].val_to_opt = &VAL_TO_OPT;
		thread_data[i].sol_found = &sol_found;
		thread_data[i].n_ss = n_ss;
		thread_data[i].platform_args = platform_args;
94b2b13d   Pedro Roque   PHACT source
880

4d26a735   Pedro Roque   Increased recogni...
881
		if (N_DEVS > 1) {
94b2b13d   Pedro Roque   PHACT source
882
883
			thread_ret = pthread_create(&threads[i], NULL, solve_on_device, (void *) &thread_data[i]);
			if (thread_ret) {
4d26a735   Pedro Roque   Increased recogni...
884
885
886
887
				fprintf(stderr, "ERROR: return code from pthread_create devices threads is %d\n", thread_ret);
				exit(-1);
			}
		} else {
94b2b13d   Pedro Roque   PHACT source
888
			result = (cl_ulong) solve_on_device(thread_data);
94b2b13d   Pedro Roque   PHACT source
889
			results[0] = result;
4d26a735   Pedro Roque   Increased recogni...
890
891
		}
	}
94b2b13d   Pedro Roque   PHACT source
892

4d26a735   Pedro Roque   Increased recogni...
893
894
895
	if (N_DEVS > 1) {
		// sum the result from all devices
		for (i = 0; i < N_DEVS; i++) {
94b2b13d   Pedro Roque   PHACT source
896
			pthread_join(threads[i], &t_result);
4d26a735   Pedro Roque   Increased recogni...
897
898
899
900
			results[i] = (unsigned long)(intptr_t)t_result;
			result += results[i];
		}
	}
94b2b13d   Pedro Roque   PHACT source
901

4d26a735   Pedro Roque   Increased recogni...
902
	if (N_DEVS > 1) {
94b2b13d   Pedro Roque   PHACT source
903
		if (WORK == OPT) {
4d26a735   Pedro Roque   Increased recogni...
904
905
906
907
908
909
910
			pthread_mutex_destroy(&opt_lock);
		}
		pthread_mutex_destroy(&stats_lock);
	}

	if (!QUIET) {
		printf("\n");
94b2b13d   Pedro Roque   PHACT source
911
	}
4d26a735   Pedro Roque   Increased recogni...
912
913
914
915
916
917
	for (i = 0; i < N_DEVS; i++) {
		STATS.solve_time += DEVICES_INFO[i].ms_solve_time;
		STATS.n_solutions += results[i];

		if (!QUIET) {
			if (DEVICES_INFO[i].stores_explored != 0) {
94b2b13d   Pedro Roque   PHACT source
918
				printf("%s (%d) took %lu ms to found %lu solution(s) on %d store(s)", DEVICES_INFO[i].dev_name, DEVICES_INFO[i].dev_type_n,
4d26a735   Pedro Roque   Increased recogni...
919
						DEVICES_INFO[i].ms_solve_time, results[i], DEVICES_INFO[i].stores_explored);
94b2b13d   Pedro Roque   PHACT source
920

94b2b13d   Pedro Roque   PHACT source
921
				if ( DEVICES_INFO[i].times_used > 1) {
4d26a735   Pedro Roque   Increased recogni...
922
923
924
					printf(" split in %u blocks,", DEVICES_INFO[i].times_used);
				}
				printf(" with an average %.03f ms per sub-search space\n", DEVICES_INFO[i].avg_1ss_solv_time);
94b2b13d   Pedro Roque   PHACT source
925

4d26a735   Pedro Roque   Increased recogni...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
			} else {
				printf("The other devices solved the CSP before %s (%d) could began\n", DEVICES_INFO[i].dev_name, DEVICES_INFO[i].dev_type_n);
			}
		}
	}

	// Compare the finish time between the first and the last device
	if (VERBOSE && N_DEVS > 1) {
		cl_ulong ms_first = DEVICES_INFO[0].ms_finish_time;
		cl_ulong ms_last = ms_first;
		unsigned int first_dev = 0;
		unsigned int last_dev = 0;

		for (i = 1; i < N_DEVS; i++) {
			if (DEVICES_INFO[i].ms_finish_time < ms_first) {
				ms_first = DEVICES_INFO[i].ms_finish_time;
				first_dev = i;
			} else if (DEVICES_INFO[i].ms_finish_time > ms_last) {
				ms_last = DEVICES_INFO[i].ms_finish_time;
				last_dev = i;
			}
		}
94b2b13d   Pedro Roque   PHACT source
948
		printf("%s (%d) finished %lu ms before %s (%d)\n", DEVICES_INFO[first_dev].dev_name, DEVICES_INFO[first_dev].dev_type_n, ms_last - ms_first,
4d26a735   Pedro Roque   Increased recogni...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
				DEVICES_INFO[last_dev].dev_name, DEVICES_INFO[last_dev].dev_type_n);
	}

	for (i = 0; i < N_DEVS; i++) {
		free(DEVICES_INFO[i].exp_values);
	}

	free(platform_args);
	free(threads);
	free(thread_data);
	free(results);

	if (WORK == OPT) {
		if (DOMAIN_TYPE == BITMAP_) {
94b2b13d   Pedro Roque   PHACT source
963
964
			for (i = 0; i < N_VS; i++) {
				b_copy(&VS[i].domain_b, &VS_LOCK_BEST[i].domain_b);
4d26a735   Pedro Roque   Increased recogni...
965
966
			}
		} else {
94b2b13d   Pedro Roque   PHACT source
967
			for (i = 0; i < N_VS; i++) {
4d26a735   Pedro Roque   Increased recogni...
968
969
970
971
972
973
974
975
976
977
978
979
980
981
				VS[i].domain_i = VS_LOCK_BEST[i].domain_i;
			}
		}

		for (i = 0; i < N_VS; i++) {
			VS[i].max = VS_LOCK_BEST[i].max;
			VS[i].min = VS_LOCK_BEST[i].min;
			VS[i].n_vals = VS_LOCK_BEST[i].n_vals;
		}
	}

#if VERIFY_SOL
	// If only one solution or best is to be found, but is incorrect
	if ((WORK == ONE || WORK == OPT) && result > 0) {
94b2b13d   Pedro Roque   PHACT source
982
983
		result = cs_check(true);
	}
4d26a735   Pedro Roque   Increased recogni...
984
985
986
987
988
989
990
991
992
#endif

	if (!QUIET) {
		printf("\n");
	}

	// when more than one device finds a solution and only one is wanted, set result to 1, as only one solution is saved
	if (WORK != CNT && result > 1) {
		result = 1;
94b2b13d   Pedro Roque   PHACT source
993
	}
4d26a735   Pedro Roque   Increased recogni...
994
995

	// remove solutions from backtracking count
94b2b13d   Pedro Roque   PHACT source
996
	if (PRINT_STATS) {
94b2b13d   Pedro Roque   PHACT source
997
		if (STATS.backtracks > result - 1) {
4d26a735   Pedro Roque   Increased recogni...
998
999
1000
1001
1002
1003
			STATS.backtracks -= result - 1;
		}
	}

	return result;
}
94b2b13d   Pedro Roque   PHACT source
1004

4d26a735   Pedro Roque   Increased recogni...
1005
/*
94b2b13d   Pedro Roque   PHACT source
1006
 * Filter the CSP by pruning values from the variables, when possible, and without labeling
4d26a735   Pedro Roque   Increased recogni...
1007
1008
 * Use 1 thread on the CPU
 * Return true if CSP is consistent after filtering
94b2b13d   Pedro Roque   PHACT source
1009
 * */
94b2b13d   Pedro Roque   PHACT source
1010
bool filter_CSP() {
4d26a735   Pedro Roque   Increased recogni...
1011
	best_sols_found = 1;	// counter for number of best solutions found
94b2b13d   Pedro Roque   PHACT source
1012
	cl_ulong result = 0;	// Number of solutions found, or 0 or 1 if only one solution is wanted
4d26a735   Pedro Roque   Increased recogni...
1013
1014
1015
1016
1017
1018
1019
1020
1021
	unsigned char sol_found = 0;	// To set to 1 when only one solution is wanted and is found (atomic read and write)
	unsigned int n_vs_cs;	// number of all variables in all constraints
	unsigned int n_cs_vs;	// number of all constraints in all variables
	unsigned int n_const_cs;	// number of all constant values in all constraints with more than one constant value
	unsigned int next_str = 0;	// Index in stores where the next unexplored sub-search space is placed (atomic read and write)
	size_t l_mem_per_wi;	// size in bytes of the local memory needed per work-item
	char* host_name = NULL;
	unsigned int n_ss = 1;		// Number of sub-search spaces created
	unsigned int depth = 0;		// Tree expansion depth needed to get n_ss disjoint search spaces
94b2b13d   Pedro Roque   PHACT source
1022
	unsigned int i, j;
4d26a735   Pedro Roque   Increased recogni...
1023
1024
1025
1026
	char* aux_name;

	filtering = true;

94b2b13d   Pedro Roque   PHACT source
1027
	STATS.n_solutions = 0;
4d26a735   Pedro Roque   Increased recogni...
1028
1029
1030
1031

	device_info filt_dev_info;
	device_args filt_dev_args;
	platf_args* platform_args;		// each platform arguments for all devices of the same platform
94b2b13d   Pedro Roque   PHACT source
1032
	cl_platform_id* platfs = NULL;		// to save all devices cl_platform_id
4d26a735   Pedro Roque   Increased recogni...
1033
1034
1035
1036
1037
1038
1039
	cl_device_id* devs = NULL;		// to save all devices cl_device_id
	cl_uint platf_cnt = 0;			// number of platforms (Intel, Nvidia...)
	cl_uint dev_cnt = 0;			// number of devices on each platform (CPU, MIC...)
	cl_int ret;		// output of clGetPlatformIDs and clGetDeviceIDs
	size_t val_size;

	// Use command line heuristics for labeling and assignment, if existent
94b2b13d   Pedro Roque   PHACT source
1040
1041
	// if not use default
	if (LABEL_MODE_COM != DEFAULT_L) {
4d26a735   Pedro Roque   Increased recogni...
1042
1043
1044
1045
1046
		LABEL_MODE = LABEL_MODE_COM;

	} else if (LABEL_MODE == DEFAULT_L) {
		LABEL_MODE = LABEL_MODE_D;
	}
94b2b13d   Pedro Roque   PHACT source
1047
	if (ASSIGN_MODE_COM != DEFAULT_A) {
94b2b13d   Pedro Roque   PHACT source
1048
		ASSIGN_MODE = ASSIGN_MODE_COM;
94b2b13d   Pedro Roque   PHACT source
1049

4d26a735   Pedro Roque   Increased recogni...
1050
1051
1052
1053
1054
	} else if (ASSIGN_MODE == DEFAULT_A) {
		ASSIGN_MODE = ASSIGN_MODE_D;
	}

	init_csp_and_d_bits();
94b2b13d   Pedro Roque   PHACT source
1055

94b2b13d   Pedro Roque   PHACT source
1056
	// discover all platforms (Intel, Nvidia, AMD,...)
4d26a735   Pedro Roque   Increased recogni...
1057
1058
	ret = clGetPlatformIDs(0, NULL, &platf_cnt);
	cl_check_error(ret, "clGetPlatformIDs", "discovering devices");
94b2b13d   Pedro Roque   PHACT source
1059
	platfs = (cl_platform_id*) malloc(platf_cnt * sizeof(cl_platform_id));
4d26a735   Pedro Roque   Increased recogni...
1060
1061
1062
	ret = clGetPlatformIDs(platf_cnt, platfs, NULL);
	cl_check_error(ret, "clGetPlatformIDs", "discovering devices");

94b2b13d   Pedro Roque   PHACT source
1063
	platform_args = (platf_args*) malloc(platf_cnt * sizeof(platf_args));
4d26a735   Pedro Roque   Increased recogni...
1064
1065
1066
1067

	// for each platform
	for (i = 0; i < platf_cnt; i++) {

94b2b13d   Pedro Roque   PHACT source
1068
		// discover the first CPU
4d26a735   Pedro Roque   Increased recogni...
1069
1070
1071
1072
		ret = clGetDeviceIDs(platfs[i], CL_DEVICE_TYPE_CPU, 0, NULL, &dev_cnt);
		devs = (cl_device_id*) malloc(sizeof(cl_device_id) * dev_cnt);
		ret = clGetDeviceIDs(platfs[i], CL_DEVICE_TYPE_CPU, dev_cnt, devs, NULL);

94b2b13d   Pedro Roque   PHACT source
1073
		platform_args[i].platform_id = platfs[i];
4d26a735   Pedro Roque   Increased recogni...
1074
1075
		platform_args[i].n_devs = dev_cnt;

94b2b13d   Pedro Roque   PHACT source
1076
		// for each device
94b2b13d   Pedro Roque   PHACT source
1077
1078
		for (j = 0; j < dev_cnt; j++) {
			// Identify the type of device (GPU, CPU, MIC,...)
94b2b13d   Pedro Roque   PHACT source
1079
			cl_device_type cl_device_type;
4d26a735   Pedro Roque   Increased recogni...
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094

			ret = clGetDeviceInfo(devs[j], CL_DEVICE_TYPE, sizeof(cl_device_type), &cl_device_type, NULL);
			cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_TYPE");

			filt_dev_info.device_id = devs[j];
			filt_dev_info.platform_id = platfs[i];
			filt_dev_info.type = CL_DEVICE_TYPE_CPU;
			filt_dev_info.dev_type_n = 1;
			filt_dev_info.n_wg = 1;
			filt_dev_info.n_wi_wg = 1;
			filt_dev_info.use_local_mem = true;
			filt_dev_info.def_n_wi_wg = 1;
			filt_dev_info.def_n_wg = 1;
			filt_dev_info.stores_explored = 0;
			filt_dev_info.last_1ss_solv_time = 0;
94b2b13d   Pedro Roque   PHACT source
1095
			filt_dev_info.avg_1ss_solv_time = 0;
4d26a735   Pedro Roque   Increased recogni...
1096
1097
			filt_dev_info.max_1ss_solv_time = 0;
			filt_dev_info.n_ss_mult = 1;
94b2b13d   Pedro Roque   PHACT source
1098
			filt_dev_info.rank = 0;
94b2b13d   Pedro Roque   PHACT source
1099
			filt_dev_info.times_used = 0;
4d26a735   Pedro Roque   Increased recogni...
1100
1101
1102
			filt_dev_info.ms_solve_time = 0;
			filt_dev_info.first_time_ranked = false;
			filt_dev_info.props_total = 0;
94b2b13d   Pedro Roque   PHACT source
1103
			filt_dev_info.last_props = 0;
4d26a735   Pedro Roque   Increased recogni...
1104
1105
1106
1107
			filt_dev_info.avg_time_prop = 0;
			filt_dev_info.last_time_prop = 0;
			filt_dev_info.max_time_prop = 0;
			filt_dev_info.ranked = false;
94b2b13d   Pedro Roque   PHACT source
1108
			filt_dev_info.working = true;
4d26a735   Pedro Roque   Increased recogni...
1109
1110
1111
1112
1113
1114
1115
1116
1117
			filt_dev_info.last_explor_time = 0;
			filt_dev_info.n_fast_blocks = 0;
			filt_dev_info.sols_found = 0;
			filt_dev_info.n_buffers = 1;
			filt_dev_info.exp_values = calloc(N_VS, sizeof(unsigned int));
			filt_dev_info.n_empty_blocks = 0;

			filt_dev_args.split_values_ext = 1;

94b2b13d   Pedro Roque   PHACT source
1118
			// get device name
4d26a735   Pedro Roque   Increased recogni...
1119
			ret = clGetDeviceInfo(devs[j], CL_DEVICE_NAME, 0, NULL, &val_size);
94b2b13d   Pedro Roque   PHACT source
1120
			cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
4d26a735   Pedro Roque   Increased recogni...
1121
1122
1123
			aux_name = (char*) malloc(val_size);
			ret = clGetDeviceInfo(devs[j], CL_DEVICE_NAME, val_size, aux_name, NULL);
			cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_NAME");
94b2b13d   Pedro Roque   PHACT source
1124
1125
1126

			// get the amount of local memory to check if it is enough
			ret = clGetDeviceInfo(filt_dev_info.device_id, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(filt_dev_info.local_mem_max_alloc),
94b2b13d   Pedro Roque   PHACT source
1127
					&filt_dev_info.local_mem_max_alloc, NULL);
4d26a735   Pedro Roque   Increased recogni...
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
			cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_LOCAL_MEM_SIZE");

			// trim leading spaces on device name
			unsigned int del = 0;
			while (isspace((unsigned char )(aux_name[del])))
				del++;
			host_name =  (char*) malloc(val_size - del);
			strcpy(host_name, &aux_name[del]);

			filt_dev_info.dev_name = (char*) malloc(val_size - del);
			strcpy(filt_dev_info.dev_name, &aux_name[del]);

			free(aux_name);

			j++;
			break;
		}

		if (j > 0) {
			break;
		}
94b2b13d   Pedro Roque   PHACT source
1149
	}
4d26a735   Pedro Roque   Increased recogni...
1150
1151
1152
	free(devs);
	free(platfs);

94b2b13d   Pedro Roque   PHACT source
1153
	if (j == 0) {
4d26a735   Pedro Roque   Increased recogni...
1154
1155
1156
1157
		fprintf(stderr, "\nThis machine does not have a CPU for filtering the CSP.\n");
		return false;
	}

94b2b13d   Pedro Roque   PHACT source
1158
	// if using intervals convert bitmaps to intervals
4d26a735   Pedro Roque   Increased recogni...
1159
1160
1161
1162
1163
1164
1165
	if (DOMAIN_TYPE == INTERVAL) {
		set_interval_domains();
	}

	// Reset variables set for labeling, because some of them may be singleton already and count the number of variables that should be labeled
	N_VS_TO_LABEL = vs_cnt_vs_to_label(VS, N_VS);

94b2b13d   Pedro Roque   PHACT source
1166
	n_vs_cs = (unsigned int)cs_cnt_vs(CS, N_CS);	// count the number of variables in all constraints
94b2b13d   Pedro Roque   PHACT source
1167
	n_cs_vs = vs_cnt_cs(VS, N_VS);	// count the number of constraints in all variables
4d26a735   Pedro Roque   Increased recogni...
1168
1169
1170
1171
1172
	n_const_cs = (unsigned int)cs_cnt_constants(CS, N_CS);	// count the number of constants constrained by all the constraints (if more than one)

	if (ASSIGN_MODE == SPLIT_VALS) {
		unsigned int split_values_ext = 1;
		unsigned int n_vals_ctr = 1;
94b2b13d   Pedro Roque   PHACT source
1173
		for (i = 0; i < N_VS; i++) {
4d26a735   Pedro Roque   Increased recogni...
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
			if (VS[i].to_label && VS[i].n_vals > n_vals_ctr) {
				n_vals_ctr = VS[i].n_vals;
			}
		}
		while (((unsigned int)(n_vals_ctr / 2)) > 0) {
			n_vals_ctr /= 2;
			split_values_ext++;
		}
		filt_dev_args.split_values_ext = split_values_ext;
	}

	if (N_VS_TO_LABEL == 0) {
		fprintf(stderr, "\nNo CSP variable is marked for labeling. Please mark at least one variable for labeling.\n\n");
		exit(-1);
94b2b13d   Pedro Roque   PHACT source
1188
1189
1190
1191
1192
1193
1194
1195
	}

	// variables that are fully expanded during sub-search spaces creation are already labeled
	if (N_VS_TO_LABEL <= 0) {
		N_VS_TO_LABEL = 1;
	}

	if (USE_TTL) {
4d26a735   Pedro Roque   Increased recogni...
1196
1197
		fprintf(stderr, "\nTTL is enabled inside the kernel.\n\n");
	}
94b2b13d   Pedro Roque   PHACT source
1198

4d26a735   Pedro Roque   Increased recogni...
1199
1200
	if (!QUIET) {
		printf("\nFiltering the CSP with 1 thread of %s", host_name);
94b2b13d   Pedro Roque   PHACT source
1201
1202
	}

4d26a735   Pedro Roque   Increased recogni...
1203
1204
1205
	// set revision to on (REV=1) or off (REV=0) by default. If PRE_LABELING==2, it is set to 1 if any propagator is capable of propagating
	// variables with more than one value in its domain
	if (PRE_LABELING == 0) {
94b2b13d   Pedro Roque   PHACT source
1206
1207
1208
		REV = 0;
	} else if (PRE_LABELING == 1) {
		REV = 1;
94b2b13d   Pedro Roque   PHACT source
1209
1210
1211
1212
1213
	}
	if (!QUIET) {
		printf(" with %s and %s heuristics", get_label_heur(), get_assign_heur());
	}
	if (REV == 1 && !QUIET) {
4d26a735   Pedro Roque   Increased recogni...
1214
1215
1216
1217
1218
		printf(" (and revision)");
	}

	if (host_name != NULL) {
		free(host_name);
94b2b13d   Pedro Roque   PHACT source
1219
1220
	}

4d26a735   Pedro Roque   Increased recogni...
1221
1222
	if (DOMAIN_TYPE == BITMAP_) {
		l_mem_per_wi = (N_VS + 3) * sizeof(cl_ushort) + N_VS * (sizeof(cl_var_p_bitmap) - sizeof(cl_bitmap) + DOMAIN_SIZE);
94b2b13d   Pedro Roque   PHACT source
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
	} else {
		l_mem_per_wi = (N_VS + 3) * sizeof(cl_ushort) + N_VS * sizeof(cl_var_p_interval);
	}

	// check if memory is enough. If not, reduce the number of wi, and wg if also needed.
#if USE_LOCAL_MEM == 0
		filt_dev_info.use_local_mem = false;
#elif USE_LOCAL_MEM == 1
		filt_dev_info.use_local_mem = true;
#endif

	if (filt_dev_info.use_local_mem && filt_dev_info.local_mem_max_alloc < l_mem_per_wi) {
		printf("\nDue to the amount of memory required, local memory will not be used in %s.\n", filt_dev_info.dev_name);
		filt_dev_info.use_local_mem = false;
	}

	filt_dev_args.n_vs_to_label = (unsigned int)N_VS_TO_LABEL;
	filt_dev_args.n_vs_cs = n_vs_cs;
	filt_dev_args.n_cs_vs = n_cs_vs;
	filt_dev_args.n_const_cs = n_const_cs;

	// get the amount of global memory to check if it is enough
	ret = clGetDeviceInfo(filt_dev_info.device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(filt_dev_info.global_mem_max_alloc),
			&filt_dev_info.global_mem_max_alloc, NULL);
	cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_MAX_MEM_ALLOC_SIZE");

	// get the maximum size of each constant memory buffer to check if it is enough
	ret = clGetDeviceInfo(filt_dev_info.device_id, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(filt_dev_info.constant_mem_max_alloc),
			&filt_dev_info.constant_mem_max_alloc, NULL);
	cl_check_error(ret, "clGetDeviceInfo", "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE");

	// number of work-items that will be created on this device
	filt_dev_args.wi_local = filt_dev_info.n_wi_wg;
	filt_dev_args.wi_total = filt_dev_info.n_wg * filt_dev_info.n_wi_wg;

	set_buffs_size(&filt_dev_args, &filt_dev_info, filtering);

	if (filt_dev_info.global_mem_used > filt_dev_info.global_mem_max_alloc) {

		fprintf(stderr, "\nPHACT is trying to use more global memory (%lu Mb) than the amount available (%lu Mb) on %s (%d)\n",
				filt_dev_info.global_mem_used / 1000000, filt_dev_info.global_mem_max_alloc / 1000000, filt_dev_info.dev_name,
				filt_dev_info.dev_type_n);

		exit(-1);
	}

	if (VERBOSE) {
		if (filt_dev_info.use_local_mem) {
			printf(", local memory");
		}

		if ((double)filt_dev_info.global_mem_used / 1000000.0 > 1.0) {
			printf(", %.02f Mb of global memory (Max. %.02f Mb) and", (double)filt_dev_info.global_mem_used / 1000000.0, (double)filt_dev_info.global_mem_max_alloc / 1000000.0);
		} else {
			printf(", %.02f Kb of global memory (Max. %.02f Mb) and", (double)filt_dev_info.global_mem_used / 1000.0, (double)filt_dev_info.global_mem_max_alloc / 1000000.0);
		}

		if (DOMAIN_TYPE == BITMAP_) {
			printf(" %d-bits bitmap domains on %d-bits words", CL_BITS_, CL_WORD_);
		} else if (DOMAIN_TYPE == INTERVAL) {
			printf(" interval domains");
		}
#if SHARED_SS > 0
		printf(" and %d shared sub-search spaces", DEVICES_ARGS[i].n_shared_stores);
#endif

	}
	if (!QUIET) {
		printf("\n\n");
	}

	filt_dev_info.n_ss_mult_max = mult_max;
	filt_dev_info.block_size = n_ss;
	filt_dev_info.n_ss_mult = 1;
	filt_dev_info.n_ss_mult_max = 1;
	filt_dev_info.first_block_size = 1;
	filt_dev_info.block_size = 1;

	// create one thread for the CPU
	threads_data thread_data;

	devs_working = 1;

	thread_data.depth = depth;
	thread_data.dev_info = &filt_dev_info;
	thread_data.dev_args = &filt_dev_args;
	thread_data.dev_number = 0;
	thread_data.next_str = &next_str;
	thread_data.val_to_opt = &VAL_TO_OPT;
	thread_data.sol_found = &sol_found;
	thread_data.n_ss = n_ss;
	thread_data.platform_args = platform_args;

	result = (cl_ulong) solve_on_device(&thread_data);

	free(platform_args);
4d26a735   Pedro Roque   Increased recogni...
1319
	free(filt_dev_info.dev_name);
94b2b13d   Pedro Roque   PHACT source
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338

	filtering = false;

	STATS.solve_time = filt_dev_info.ms_solve_time;

	free(filt_dev_info.exp_values);

	return (bool)result;
}

/*
 * Thread responsible for solving sub-search spaces on a device
 * thread_arg - structure with all thread arguments
 */
void* solve_on_device(void* thread_arg) {
	struct threads_data* thread_d;
	thread_d = (struct threads_data*) thread_arg;

	unsigned int depth = thread_d->depth;	// Tree expansion depth needed to get n_ss disjoint search spaces
4d26a735   Pedro Roque   Increased recogni...
1339
	unsigned int n_ss = thread_d->n_ss;		// Number of sub-search spaces created
94b2b13d   Pedro Roque   PHACT source
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
	unsigned int* next_str = thread_d->next_str;	// Index in stores where the next unexplored sub-search space is placed (atomic read and write)
	cl_uint* val_to_opt = thread_d->val_to_opt;	// Max value on the domain of the variable to optimize (atomic read and write)
	unsigned char* sol_found = thread_d->sol_found;	// To set to 1 when only one solution is wanted and is found (atomic read and write)
	device_info* this_dev_info = &thread_d->dev_info[thread_d->dev_number];	// Information about the device to use
	device_info* all_dev_info = thread_d->dev_info;	// Information about all the device to use
	device_args* this_dev_args = &thread_d->dev_args[thread_d->dev_number];	// Device arguments (buffers, etc.)
	cl_ulong result = 0;	// 0, 1 or number of solutions found by this device
	cl_ulong total_result = 0;	// 0, 1 or number of solutions found by this device
	unsigned int stores_idx;	// index of the next unexplored store to pick
	// To get and print elapsed times
	char elapsed_time[40];
4d26a735   Pedro Roque   Increased recogni...
1351
	char start_time[40];
94b2b13d   Pedro Roque   PHACT source
1352
	char end_time[40];
4d26a735   Pedro Roque   Increased recogni...
1353
	struct timeval start, end;
94b2b13d   Pedro Roque   PHACT source
1354

4d26a735   Pedro Roque   Increased recogni...
1355
	if (N_DEVS > 1 && !filtering) {
94b2b13d   Pedro Roque   PHACT source
1356
1357
1358
1359
1360
1361
1362
		pthread_barrier_wait(&barrier);
	}

	if (VERBOSE) {
		gettimeofday(&start, NULL);
	}

4d26a735   Pedro Roque   Increased recogni...
1363
	// Initialize OpenCL objects on this device
94b2b13d   Pedro Roque   PHACT source
1364
1365
1366
1367
1368
1369
1370
	init_device(this_dev_info, this_dev_args, filtering);

#if RUN_IN_CUDA
	if (N_DEVS > 1 && !filtering) {
		pthread_barrier_wait(&barrier);
	}
#endif
4d26a735   Pedro Roque   Increased recogni...
1371
1372
1373
1374
1375
1376
1377
1378

	// calculate time spent for initializing the devices
	if (VERBOSE) {
		gettimeofday(&end, NULL);
		format_elapsed_time_s_ms(elapsed_time, start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
		format_time_s_ms(start_time, start.tv_sec, start.tv_usec);
		format_time_s_ms(end_time, end.tv_sec, end.tv_usec);

94b2b13d   Pedro Roque   PHACT source
1379
1380
1381
1382
1383
1384
1385
1386
		printf("%s...%s = %s (s.ms) -> %s (%d) was initialized\n", start_time, end_time, elapsed_time, this_dev_info->dev_name, this_dev_info->dev_type_n);
	}

	// Get the index of the unexplored sub-search space to explore next
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
	stores_idx = InterlockedAdd(next_str, this_dev_info->block_size) - this_dev_info->block_size;
#else
	stores_idx = __atomic_fetch_add(next_str, this_dev_info->block_size, __ATOMIC_SEQ_CST);
4d26a735   Pedro Roque   Increased recogni...
1387
#endif
94b2b13d   Pedro Roque   PHACT source
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400

	if (WORK == CNT) {
		while (stores_idx < n_ss) {

			this_dev_info->first_store = stores_idx;
			if (stores_idx + this_dev_info->block_size >= n_ss) {
				this_dev_info->block_size = n_ss - stores_idx;
			}
			this_dev_info->last_store = stores_idx + this_dev_info->block_size;

			if (!VERBOSE && !QUIET) {
				printf("%s (%d) will receive more %d stores\n", this_dev_info->dev_name, this_dev_info->dev_type_n, this_dev_info->block_size);
			}
4d26a735   Pedro Roque   Increased recogni...
1401
1402
1403
1404
1405
1406

			gettimeofday(&start, NULL);

			// solve the sub-search spaces on this device for finding all the solutions
			result = count_sols(this_dev_args, this_dev_info, depth, n_ss, &stats_lock, filtering);

94b2b13d   Pedro Roque   PHACT source
1407
			gettimeofday(&end, NULL);
4d26a735   Pedro Roque   Increased recogni...
1408

94b2b13d   Pedro Roque   PHACT source
1409
1410
1411
1412
			total_result += result;
			this_dev_info->sols_found += result;

			this_dev_info->last_explor_time = (double)(end.tv_sec - start.tv_sec) * 1000.0;
4d26a735   Pedro Roque   Increased recogni...
1413
			this_dev_info->last_explor_time += (double)(end.tv_usec - start.tv_usec) / 1000.0;
94b2b13d   Pedro Roque   PHACT source
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426

			// update the number of stores this device explored and the number of times it was used
			this_dev_info->stores_explored += this_dev_info->block_size;
			this_dev_info->times_used++;

			// update the last elapsed time this device needs to solve on sub-search space and the cl_find_all_sol elapsed time
			this_dev_info->last_1ss_solv_time = (float)get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec) / (float)this_dev_info->block_size;
			this_dev_info->ms_solve_time += get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
			this_dev_info->avg_1ss_solv_time = (float)this_dev_info->ms_solve_time / (float) this_dev_info->stores_explored;

			this_dev_info->last_time_prop = (float)((float)get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec) / ((double)this_dev_info->last_props * 1.0));

			if (VERBOSE) {
4d26a735   Pedro Roque   Increased recogni...
1427
				format_elapsed_time_s_ms(elapsed_time, start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
94b2b13d   Pedro Roque   PHACT source
1428
				format_time_s_ms(start_time, start.tv_sec, start.tv_usec);
4d26a735   Pedro Roque   Increased recogni...
1429
				format_time_s_ms(end_time, end.tv_sec, end.tv_usec);
94b2b13d   Pedro Roque   PHACT source
1430
1431
1432
1433
1434
1435
1436

				if (!filtering) {
					printf("%s...%s = %s (s.ms) -> %s (%d) found %lu solution(s) on %u store(s) (%u...%u)", start_time, end_time, elapsed_time,
							this_dev_info->dev_name, this_dev_info->dev_type_n, result, this_dev_info->block_size, this_dev_info->first_store, this_dev_info->last_store - 1);

					if (this_dev_info->n_ss_mult > 1) {
						printf(" expanded %u times (Max. %u times)", this_dev_info->n_ss_mult, this_dev_info->n_ss_mult_max);
4d26a735   Pedro Roque   Increased recogni...
1437
					}
94b2b13d   Pedro Roque   PHACT source
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
					printf(", taking %.03f ms per ss", this_dev_info->last_1ss_solv_time);

					if (this_dev_info->rank > 0.000) {
						printf(" with a rank of %.03f\n", this_dev_info->rank);
					} else {
						printf("\n");
					}

				} else {
					printf("%s...%s = %s (s.ms) -> %s (%d) filtered the CSP\n", start_time, end_time, elapsed_time, this_dev_info->dev_name, this_dev_info->dev_type_n);
				}
			}

			if (*next_str < n_ss) {
				// calculate next amount of stores to send to device
				set_next_block_size(all_dev_info, thread_d->dev_number, n_ss, next_str);

				if (this_dev_info->block_size == 0) {
					break;
				}

				// Get the index of the unexplored sub-search space to explore next
4d26a735   Pedro Roque   Increased recogni...
1460
1461
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
				stores_idx = InterlockedAdd(next_str, this_dev_info->block_size) - this_dev_info->block_size;
94b2b13d   Pedro Roque   PHACT source
1462
#else
4d26a735   Pedro Roque   Increased recogni...
1463
1464
1465
1466
1467
1468
				stores_idx = __atomic_fetch_add(next_str, this_dev_info->block_size, __ATOMIC_SEQ_CST);
#endif
				if (stores_idx < n_ss && stores_idx + this_dev_info->block_size > n_ss) {
					this_dev_info->block_size = n_ss - stores_idx;
				}
			} else {
94b2b13d   Pedro Roque   PHACT source
1469
1470
1471
1472
				break;
			}
		}
	} else if (WORK == ONE) {
4d26a735   Pedro Roque   Increased recogni...
1473
		while ((*sol_found) == 0 && (stores_idx < n_ss || (stores_idx == 1 && n_ss == 1))) {
94b2b13d   Pedro Roque   PHACT source
1474
1475

			this_dev_info->first_store = stores_idx;
4d26a735   Pedro Roque   Increased recogni...
1476
1477
1478
			if (stores_idx + this_dev_info->block_size >= n_ss) {
				this_dev_info->block_size = n_ss - stores_idx;
			}
94b2b13d   Pedro Roque   PHACT source
1479
			this_dev_info->last_store = stores_idx + this_dev_info->block_size;
4d26a735   Pedro Roque   Increased recogni...
1480
1481

			// for elapsed time calculation
94b2b13d   Pedro Roque   PHACT source
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
			if (!VERBOSE && !QUIET) {
				printf("%s (%d) will receive more %d stores\n", this_dev_info->dev_name, this_dev_info->dev_type_n, this_dev_info->block_size);
			}

			gettimeofday(&start, NULL);

			// solve the sub-search spaces on this device for finding one solution
			result = find_one_sol(this_dev_args, this_dev_info, sol_found, depth, n_ss, &stats_lock, filtering);

			gettimeofday(&end, NULL);

			total_result += result;
			this_dev_info->sols_found += result;

			this_dev_info->last_explor_time = (float)(end.tv_sec - start.tv_sec) * 1000.0;
			this_dev_info->last_explor_time += (float)(end.tv_usec - start.tv_usec) / 1000.0;
4d26a735   Pedro Roque   Increased recogni...
1498

94b2b13d   Pedro Roque   PHACT source
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
			// update the number of stores this device explored and the number of times it was used
			this_dev_info->stores_explored += this_dev_info->block_size;
			this_dev_info->times_used++;

			// update the last elapsed time this device needs to solve on sub-search space and the cl_find_all_sol elapsed time
			this_dev_info->last_1ss_solv_time = (float)get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec) / (float) this_dev_info->block_size;
			this_dev_info->ms_solve_time += get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
			this_dev_info->avg_1ss_solv_time = (float)this_dev_info->ms_solve_time / (float)this_dev_info->stores_explored;

			this_dev_info->last_time_prop = (float)((float)get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec) / ((float)this_dev_info->last_props * 1.0));

			if (VERBOSE) {
				format_elapsed_time_s_ms(elapsed_time, start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
				format_time_s_ms(start_time, start.tv_sec, start.tv_usec);
				format_time_s_ms(end_time, end.tv_sec, end.tv_usec);

				if (!filtering) {
					printf("%s...%s = %s (s.ms) -> %s (%d) found %lu solution(s) on %u store(s) (%u...%u)", start_time, end_time, elapsed_time,
							this_dev_info->dev_name, this_dev_info->dev_type_n, result, this_dev_info->block_size, this_dev_info->first_store, this_dev_info->last_store - 1);

					if (this_dev_info->n_ss_mult > 1) {
						printf(" expanded %u times (Max. %u times)", this_dev_info->n_ss_mult, this_dev_info->n_ss_mult_max);
					}
					printf(", taking %.03f ms per ss", this_dev_info->last_1ss_solv_time);

					if (this_dev_info->rank > 0.000) {
						printf(" with a previous rank of %.03f\n", this_dev_info->rank);
					} else {
						printf("\n");
					}

				} else {
4d26a735   Pedro Roque   Increased recogni...
1531
					printf("%s...%s = %s (s.ms) -> %s (%d) filtered the CSP\n", start_time, end_time, elapsed_time, this_dev_info->dev_name, this_dev_info->dev_type_n);
94b2b13d   Pedro Roque   PHACT source
1532
1533
1534
1535
1536
1537
				}
			}

			// calculate next amount of stores to send to device
			if (*next_str < n_ss) {
				set_next_block_size(all_dev_info, thread_d->dev_number, n_ss, next_str);
4d26a735   Pedro Roque   Increased recogni...
1538
1539

				if (this_dev_info->block_size == 0) {
94b2b13d   Pedro Roque   PHACT source
1540
1541
1542
1543
					break;
				}

				// Get the index of the unexplored sub-search space to explore next
4d26a735   Pedro Roque   Increased recogni...
1544
1545
1546
1547
1548
1549
1550
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
				stores_idx = InterlockedAdd(next_str, this_dev_info->block_size) - this_dev_info->block_size;
#else
				stores_idx = __atomic_fetch_add(next_str, this_dev_info->block_size, __ATOMIC_SEQ_CST);
#endif
				if (stores_idx < n_ss && stores_idx + this_dev_info->block_size > n_ss) {
					this_dev_info->block_size = n_ss - stores_idx;
94b2b13d   Pedro Roque   PHACT source
1551
1552
				}
			} else {
4d26a735   Pedro Roque   Increased recogni...
1553
				break;
94b2b13d   Pedro Roque   PHACT source
1554
1555
1556
1557
1558
1559
1560
			}
		}
		// if WORK == OPT
	} else {
		while (stores_idx < n_ss) {

			this_dev_info->first_store = stores_idx;
4d26a735   Pedro Roque   Increased recogni...
1561
			if (stores_idx + this_dev_info->block_size >= n_ss) {
94b2b13d   Pedro Roque   PHACT source
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
				this_dev_info->block_size = n_ss - stores_idx;
			}
			this_dev_info->last_store = stores_idx + this_dev_info->block_size;

			if (!VERBOSE && !QUIET) {
				printf("%s (%d) will receive more %d stores\n", this_dev_info->dev_name, this_dev_info->dev_type_n, this_dev_info->block_size);
			}

			gettimeofday(&start, NULL);

			// solve the sub-search spaces on this device for finding all the solutions
4d26a735   Pedro Roque   Increased recogni...
1573
			result = find_best_sol(this_dev_args, this_dev_info, val_to_opt, &opt_lock, depth, n_ss, &stats_lock, filtering);
94b2b13d   Pedro Roque   PHACT source
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603

			gettimeofday(&end, NULL);

			total_result += result;
			best_sols_found += (unsigned int)result;
			this_dev_info->sols_found += result;

			this_dev_info->last_explor_time = (float)(end.tv_sec - start.tv_sec) * 1000.0;
			this_dev_info->last_explor_time += (float)(end.tv_usec - start.tv_usec) / 1000.0;

			// update the number of stores this device explored and the number of times it was used
			this_dev_info->stores_explored += this_dev_info->block_size;
			this_dev_info->times_used++;

			// update the last elapsed time this device needs to solve on sub-search space and the cl_find_all_sol elapsed time
			this_dev_info->last_1ss_solv_time = (float)get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec) / (float) this_dev_info->block_size;
			this_dev_info->ms_solve_time += get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
			this_dev_info->avg_1ss_solv_time = (float)this_dev_info->ms_solve_time / (float)this_dev_info->stores_explored;

			this_dev_info->last_time_prop = (float)((float)get_elapsed_ms(start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec) / ((float)this_dev_info->last_props * 1.0));

			if (VERBOSE) {
				format_elapsed_time_s_ms(elapsed_time, start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
				format_time_s_ms(start_time, start.tv_sec, start.tv_usec);
				format_time_s_ms(end_time, end.tv_sec, end.tv_usec);

				if (!filtering) {
					printf("%s...%s = %s (s.ms) -> %s (%d) found %lu best solution(s) on %u store(s) (%u...%u)", start_time, end_time, elapsed_time,
							this_dev_info->dev_name, this_dev_info->dev_type_n, result, this_dev_info->block_size, this_dev_info->first_store, this_dev_info->last_store - 1);

4d26a735   Pedro Roque   Increased recogni...
1604
					if (this_dev_info->n_ss_mult > 1) {
94b2b13d   Pedro Roque   PHACT source
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
						printf(" expanded %u times (Max. %u times)", this_dev_info->n_ss_mult, this_dev_info->n_ss_mult_max);
					}
					printf(", taking %.03f ms per ss", this_dev_info->last_1ss_solv_time);

					if (this_dev_info->rank > 0.000) {
						printf(" with a previous rank of %.03f\n", this_dev_info->rank);
					} else {
						printf("\n");
					}

				} else {
					printf("%s...%s = %s (s.ms) -> %s (%d) filtered the CSP\n", start_time, end_time, elapsed_time, this_dev_info->dev_name, this_dev_info->dev_type_n);
4d26a735   Pedro Roque   Increased recogni...
1617
1618
				}
			}
94b2b13d   Pedro Roque   PHACT source
1619
1620
1621
1622
1623
1624

			if (*next_str < n_ss) {
				// calculate next amount of stores to send to device
				set_next_block_size(all_dev_info, thread_d->dev_number, n_ss, next_str);

				if (this_dev_info->block_size == 0) {
4d26a735   Pedro Roque   Increased recogni...
1625
1626
					break;
				}
94b2b13d   Pedro Roque   PHACT source
1627

4d26a735   Pedro Roque   Increased recogni...
1628
				// Get the index of the unexplored sub-search space to explore next
94b2b13d   Pedro Roque   PHACT source
1629
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
4d26a735   Pedro Roque   Increased recogni...
1630
1631
				stores_idx = InterlockedAdd(next_str, this_dev_info->block_size) - this_dev_info->block_size;
#else
94b2b13d   Pedro Roque   PHACT source
1632
1633
1634
1635
1636
1637
1638
1639
				stores_idx = __atomic_fetch_add(next_str, this_dev_info->block_size, __ATOMIC_SEQ_CST);
#endif
				if (stores_idx < n_ss && stores_idx + this_dev_info->block_size > n_ss) {
					this_dev_info->block_size = n_ss - stores_idx;
				}
			} else {
				break;
			}
4d26a735   Pedro Roque   Increased recogni...
1640
1641
		}
	}
94b2b13d   Pedro Roque   PHACT source
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

	// for elapsed time calculation
	if (VERBOSE) {
		gettimeofday(&start, NULL);
	}

	// clear device objects
	release_device(this_dev_args, this_dev_info, filtering);

	if (VERBOSE) {
		gettimeofday(&end, NULL);
		this_dev_info->ms_finish_time = (unsigned long)end.tv_sec * 1000 + (unsigned long)end.tv_usec / 1000;
	}
4d26a735   Pedro Roque   Increased recogni...
1655
1656

	if (VERBOSE) {
94b2b13d   Pedro Roque   PHACT source
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
		gettimeofday(&end, NULL);
		format_elapsed_time_s_ms(elapsed_time, start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
		format_time_s_ms(start_time, start.tv_sec, start.tv_usec);
		format_time_s_ms(end_time, end.tv_sec, end.tv_usec);

		printf("%s...%s = %s (s.ms) -> %s (%d) was released\n", start_time, end_time, elapsed_time, this_dev_info->dev_name, this_dev_info->dev_type_n);
	}

	if (N_DEVS > 1 && !filtering) {
		return (void *) (intptr_t) total_result;
	} else {
		return (void *) (cl_ulong) total_result;
	}
}

/*
 * Load balancing between all devices
 * dev_info - all devices information
 * dev_idx - index of dev_info of the device to calculate the next amount of stores to send to device
 * n_ss - total number of sub-search spaces created
 * last_str_explored - last store explored
 */
void set_next_block_size(device_info* dev_info, unsigned int dev_idx, unsigned int n_ss, unsigned int* last_str_explored) {
	float avg_sum = 0;
	float* avg_prop_solv_time = malloc(N_DEVS * sizeof(float));
	bool all_devs_used;
	unsigned int devs_ranked_;
	unsigned int devs_working_;
	unsigned int i;
	unsigned int fastest_dev = 0;
	unsigned int fastest_dev_prop_solv_time = UINT_MAX;
	unsigned int last_str_explored_;

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
	last_str_explored_ = InterlockedAdd(last_str_explored, 0);
4d26a735   Pedro Roque   Increased recogni...
1692
#else
94b2b13d   Pedro Roque   PHACT source
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
	last_str_explored_ = __atomic_fetch_add(last_str_explored, 0, __ATOMIC_SEQ_CST);
#endif

	for (i = 0; i < N_DEVS; i++) {
		if (dev_info[i].working) {
			if (avg_prop_solv_time[i] > 0 && avg_prop_solv_time[i] < fastest_dev_prop_solv_time) {
				fastest_dev_prop_solv_time = (unsigned int)avg_prop_solv_time[i];
				fastest_dev = i;
			}
		}
	}

4d26a735   Pedro Roque   Increased recogni...
1705
1706
	// More one device ranked
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
94b2b13d   Pedro Roque   PHACT source
1707
1708
1709
1710
1711
1712
	devs_ranked_ = InterlockedAdd(&devs_ranked, 0);
	devs_working_ = InterlockedAdd(&devs_working_, 0);
#else
	devs_ranked_ = __atomic_add_fetch(&devs_ranked, 0, __ATOMIC_SEQ_CST);
	devs_working_ = __atomic_add_fetch(&devs_working, 0, __ATOMIC_SEQ_CST);
#endif
4d26a735   Pedro Roque   Increased recogni...
1713
1714

	dev_info[dev_idx].n_ss_mult = 1;
94b2b13d   Pedro Roque   PHACT source
1715

4d26a735   Pedro Roque   Increased recogni...
1716
	// only one device so take the remaining ss
94b2b13d   Pedro Roque   PHACT source
1717
	if (devs_working_ == 1) {
4d26a735   Pedro Roque   Increased recogni...
1718
1719
		dev_info[dev_idx].block_size = n_ss - last_str_explored_;

94b2b13d   Pedro Roque   PHACT source
1720
1721
1722
1723
1724
1725
1726
1727
	} else {
		// if counting all the solutions
		if (WORK == CNT) {

			if (dev_info[dev_idx].props_total == 0) {
				dev_info[dev_idx].props_total = 1;
			}

4d26a735   Pedro Roque   Increased recogni...
1728
1729
			if (dev_info[dev_idx].last_1ss_solv_time > dev_info[dev_idx].max_1ss_solv_time) {
				dev_info[dev_idx].max_1ss_solv_time = dev_info[dev_idx].last_1ss_solv_time;
94b2b13d   Pedro Roque   PHACT source
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
			}

			if (dev_info[dev_idx].last_time_prop > dev_info[dev_idx].max_time_prop) {
				dev_info[dev_idx].max_time_prop = dev_info[dev_idx].last_time_prop;
			}

			// update the average time needed to run one propagator
			dev_info[dev_idx].avg_time_prop = (float)dev_info[dev_idx].ms_solve_time / (float)dev_info[dev_idx].props_total * 1000;

			for (i = 0; i < N_DEVS; i++) {
				avg_prop_solv_time[i] = dev_info[i].avg_time_prop;
			}

4d26a735   Pedro Roque   Increased recogni...
1743
1744
			// if this device wasn't ranked yet
			if (!dev_info[dev_idx].ranked && dev_info[dev_idx].times_used == N_FIRST_BLOCKS) {
94b2b13d   Pedro Roque   PHACT source
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
				dev_info[dev_idx].ranked = true;

				// More one device ranked
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
				devs_ranked_ = InterlockedAdd(&devs_ranked, 1);
#else
				devs_ranked_ = __atomic_add_fetch(&devs_ranked, 1, __ATOMIC_SEQ_CST);
#endif
			}

			// if the device took more than 1 s to explore the previous block, decrease the size of the next block to half. For the first 3 block only
			if (dev_info[dev_idx].times_used < N_FIRST_BLOCKS && dev_info[dev_idx].last_explor_time > MS_HALF_FIRST_BLOCKS) {
				dev_info[dev_idx].block_size /= 2;
			}

			// if only one device is already ranked, and this one already explored two blocks, doubles the size of the next block, if that is not be too big
			if (devs_ranked_ == 1 && dev_info[dev_idx].times_used >= N_FIRST_BLOCKS && dev_info[dev_idx].block_size * 2 < (n_ss - last_str_explored_) * PERCENT_REM_SS_DOUBLE) {
				dev_info[dev_idx].block_size *= 2;

			// After this point more than one device are already ranked
			} else if (devs_ranked_ == N_DEVS) {
				// update current device rank
				for (i = 0; i < N_DEVS; i++) {
					if (dev_info[i].working) {
						if (avg_prop_solv_time[i] > 0) {
							avg_sum += 1 / avg_prop_solv_time[i];
						}
					}
				}
				if (avg_prop_solv_time[dev_idx] > 0 && avg_sum > 0) {
					dev_info[dev_idx].rank = 1 / avg_prop_solv_time[dev_idx] / avg_sum;

					// next block size
					if (dev_info[dev_idx].type == CL_DEVICE_TYPE_CPU) {
						dev_info[dev_idx].block_size = (unsigned int)(dev_info[dev_idx].rank * (float)(n_ss - last_str_explored_) * PERCENT_REM_SS_RANK_CPU);
4d26a735   Pedro Roque   Increased recogni...
1780

94b2b13d   Pedro Roque   PHACT source
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
					} else if (dev_info[dev_idx].type == CL_DEVICE_TYPE_GPU) {
						dev_info[dev_idx].block_size = (unsigned int)(dev_info[dev_idx].rank * (float)(n_ss - last_str_explored_) * PERCENT_REM_SS_RANK_GPU);

						// ACC
					} else {
						dev_info[dev_idx].block_size = (unsigned int)(dev_info[dev_idx].rank * (float)(n_ss - last_str_explored_) * PERCENT_REM_SS_RANK_ACC);
					}
				}

				// if this device is estimated to take less than 500 ms to solve the remaining ss, takes them all
4d26a735   Pedro Roque   Increased recogni...
1791
				if ((float)(n_ss - last_str_explored_) * dev_info[dev_idx].avg_1ss_solv_time < MS_TAKE_ALL) {
94b2b13d   Pedro Roque   PHACT source
1792
1793
					dev_info[dev_idx].block_size = n_ss - last_str_explored_;
				}
4d26a735   Pedro Roque   Increased recogni...
1794
1795
			}

94b2b13d   Pedro Roque   PHACT source
1796
1797
1798
1799
1800
1801
		// if optimizing try to deliver blocks that take 1s to explore
		} else if (WORK == OPT) {

			if (dev_info[dev_idx].last_explor_time < FAST_BLOCKS_MS_OPT) {
				dev_info[dev_idx].n_fast_blocks++;

4d26a735   Pedro Roque   Increased recogni...
1802
1803
			} else {
				dev_info[dev_idx].n_fast_blocks = 0;
94b2b13d   Pedro Roque   PHACT source
1804

4d26a735   Pedro Roque   Increased recogni...
1805
				if (dev_info[dev_idx].last_explor_time > FAST_BLOCKS_MS_OPT) {
94b2b13d   Pedro Roque   PHACT source
1806
					dev_info[dev_idx].block_size /= 2;
4d26a735   Pedro Roque   Increased recogni...
1807
1808
				}
			}
94b2b13d   Pedro Roque   PHACT source
1809
1810
1811
1812
1813
1814
1815
1816

			if (dev_info[dev_idx].n_fast_blocks == N_FAST_BLOCKS_OPT) {
				dev_info[dev_idx].block_size += 1 + (unsigned int)(PERCENT_BLOCKS_ADD * (double)dev_info[dev_idx].block_size);
				dev_info[dev_idx].n_fast_blocks = 0;
			}

		// if finding one solution and all devices have explored at least three blocks each, try to deliver blocks that take 2s to explore
		} else {
4d26a735   Pedro Roque   Increased recogni...
1817
1818
			all_devs_used = true;

94b2b13d   Pedro Roque   PHACT source
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
			for (i = 0; i < N_DEVS; i++) {
				if (dev_info[i].times_used < N_FIRST_BLOCKS) {
					all_devs_used = false;
					break;
				}
			}

			if (dev_info[dev_idx].avg_1ss_solv_time != 0 && all_devs_used == true) {
				dev_info[dev_idx].block_size = (unsigned int)(FAST_BLOCKS_MS_ONE / dev_info[dev_idx].avg_1ss_solv_time);
			}

			if (dev_info[dev_idx].last_explor_time > FAST_BLOCKS_MS_ONE * 2) {
				dev_info[dev_idx].block_size /= 2;
4d26a735   Pedro Roque   Increased recogni...
1832
1833
			}
		}
94b2b13d   Pedro Roque   PHACT source
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
	}

	if (dev_info[dev_idx].times_used / TIMES_USED_TRESHOLD > 1.0 && (SS_REM_PERC_TRESHOLD * n_ss) < (n_ss - last_str_explored_)) {
		dev_info[dev_idx].block_size *= (unsigned int)(dev_info[dev_idx].times_used / TIMES_USED_TRESHOLD);
	}

	// if the block size is close to 0, stop it
	if (dev_info[dev_idx].block_size == 0) {

		dev_info[dev_idx].n_empty_blocks++;

		if (dev_info[dev_idx].n_empty_blocks >= N_EMPTY_BLOCKS && dev_idx != fastest_dev && dev_info[dev_idx].type == CL_DEVICE_TYPE_GPU && !all_GPUs) {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
			devs_working_ = InterlockedDecrement(&devs_working);
#else
			devs_working_ = __atomic_sub_fetch(&devs_working, 1, __ATOMIC_SEQ_CST);
#endif
			if (devs_working_ > 0) {
				dev_info[dev_idx].block_size = 0;
				dev_info[dev_idx].working = false;

			} else {
				dev_info[dev_idx].block_size = n_ss - last_str_explored_;
			}

		} else {
			dev_info[dev_idx].block_size = 1;
		}

	} else {
		dev_info[dev_idx].n_empty_blocks = 0;
	}

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
	devs_working_ = InterlockedAdd(&devs_working, 0);
#else
4d26a735   Pedro Roque   Increased recogni...
1870
	devs_working_ = __atomic_add_fetch(&devs_working, 0, __ATOMIC_SEQ_CST);
94b2b13d   Pedro Roque   PHACT source
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
#endif
	if (devs_working_ == 1 && dev_info[dev_idx].working) {
		dev_info[dev_idx].block_size = n_ss - last_str_explored_;
	}

#if SS_MULTIPLIER
	if (dev_info[dev_idx].block_size > 0) {
		//GPU
		if (dev_info[dev_idx].type == CL_DEVICE_TYPE_GPU && dev_info[dev_idx].block_size < SS_GPU / (GPU_DEFAULT_N_WI / (double)dev_info[dev_idx].n_wi_wg * 1.0)
				/ (GPU_DEFAULT_N_WG / (double)dev_info[dev_idx].n_wg)) {

			dev_info[dev_idx].n_ss_mult = (unsigned int)((SS_GPU / (GPU_DEFAULT_N_WI / (double)dev_info[dev_idx].n_wi_wg) / (GPU_DEFAULT_N_WG / (double)dev_info[dev_idx].n_wg * 1.0))
4d26a735   Pedro Roque   Increased recogni...
1883
					/ dev_info[dev_idx].block_size);
94b2b13d   Pedro Roque   PHACT source
1884
		// ACC
4d26a735   Pedro Roque   Increased recogni...
1885
		} else if (dev_info[dev_idx].type == CL_DEVICE_TYPE_ACCELERATOR && dev_info[dev_idx].block_size < SS_ACC / (dev_info[dev_idx].compute_units /
94b2b13d   Pedro Roque   PHACT source
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
				(double)dev_info[dev_idx].n_wg * 1.0)) {
			dev_info[dev_idx].n_ss_mult = (unsigned int)(SS_ACC / (dev_info[dev_idx].compute_units / (double)dev_info[dev_idx].n_wg * 1.0) / dev_info[dev_idx].block_size);
		// CPU
		} else if (DEVICES_INFO[dev_idx].type == CL_DEVICE_TYPE_CPU && dev_info[dev_idx].block_size < SS_CPU * dev_info[dev_idx].compute_units /
				(dev_info[dev_idx].compute_units / (double)dev_info[dev_idx].n_wg * 1.0)) {
			dev_info[dev_idx].n_ss_mult = (unsigned int)((SS_CPU * dev_info[dev_idx].compute_units) / (dev_info[dev_idx].compute_units / (double)dev_info[dev_idx].n_wg * 1.0) /
					dev_info[dev_idx].block_size);
		}

		if (dev_info[dev_idx].n_ss_mult > mult_max) {
4d26a735   Pedro Roque   Increased recogni...
1896
			dev_info[dev_idx].n_ss_mult = mult_max;
94b2b13d   Pedro Roque   PHACT source
1897
		} else if (dev_info[dev_idx].n_ss_mult == 0) {
4d26a735   Pedro Roque   Increased recogni...
1898
			dev_info[dev_idx].n_ss_mult = 1;
94b2b13d   Pedro Roque   PHACT source
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
		}
	}
#endif
	
	free(avg_prop_solv_time);
}

/*
 * Calculate number of stores to create and fill all stores with disjoint sub-trees
 * Stores are only filled to depth, because all the remaining domains are equal in all stores
 * depth - depth of tree needed to expand to fill stores
 * n_ss - to save the number of stores to create
 * strs - stores to fill
 */
void split_ss(unsigned int* depth, unsigned int* n_ss, unsigned int n_vs_to_label) {
	unsigned int n_strs; // maximum number of ss to create
	unsigned int vs_to_label_cntr = 0;
4d26a735   Pedro Roque   Increased recogni...
1916
	unsigned int i, j;
94b2b13d   Pedro Roque   PHACT source
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953

	EXP_VALUES = calloc(N_VS, sizeof(unsigned int));

	// if just one search space is to be used
	if ((N_DEVS == 1 && DEVICES_INFO[0].n_wg * DEVICES_INFO[0].n_wi_wg == 1 && N_SS == 0) || N_SS == 1) {
		(*depth) = 0;
		(*n_ss) = 1;
	} else {
		// if the user wants to use the default number of sub-search spaces
		if (N_SS == 0) {
			// if going to use more than one device
			if (N_DEVS > 1) {
				n_strs = 0;
				// base on the CPU number of cores
				for (i = 0; i < N_DEVS; i++) {
					if (DEVICES_INFO[i].type == CL_DEVICE_TYPE_CPU) {
						n_strs = SS_CPU * DEVICES_INFO[i].compute_units;
						break;
					}
				}
				// no CPU, get the device with less cores
				if (n_strs == 0) {
					for (i = 0; i < N_DEVS; i++) {
						// GPU
						if (DEVICES_INFO[0].type == CL_DEVICE_TYPE_GPU) {
							if (SS_GPU > n_strs) {
								n_strs = SS_GPU;
							}
						// MIC
						} else if (DEVICES_INFO[0].type == CL_DEVICE_TYPE_ACCELERATOR) {
							if (SS_ACC > n_strs) {
								n_strs = SS_ACC;
							}
						// CPU
						} else {
							n_strs = SS_GPU;
						}
4d26a735   Pedro Roque   Increased recogni...
1954
					}
94b2b13d   Pedro Roque   PHACT source
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
				}

			// if only one device
			} else if (DEVICES_INFO[0].type == CL_DEVICE_TYPE_GPU) {

				if (DEVICES_INFO[0].n_wg == DEVICES_INFO[0].def_n_wg && DEVICES_INFO[0].n_wi_wg == DEVICES_INFO[0].def_n_wi_wg) {
					n_strs = SS_GPU;
				} else {
					n_strs = (unsigned int)((DEVICES_INFO[0].n_wg * DEVICES_INFO[0].n_wi_wg * SS_GPU) / (DEVICES_INFO[0].def_n_wg * DEVICES_INFO[0].def_n_wi_wg));
				}

			} else if (DEVICES_INFO[0].type == CL_DEVICE_TYPE_ACCELERATOR) {

				if (DEVICES_INFO[0].n_wg == DEVICES_INFO[0].def_n_wg && DEVICES_INFO[0].n_wi_wg == DEVICES_INFO[0].def_n_wi_wg) {
					n_strs = SS_ACC;
				} else {
					n_strs = (unsigned int)((DEVICES_INFO[0].n_wg * DEVICES_INFO[0].n_wi_wg * SS_ACC) / (DEVICES_INFO[0].def_n_wg * DEVICES_INFO[0].def_n_wi_wg));
				}

			} else {

				if (DEVICES_INFO[0].n_wg == DEVICES_INFO[0].def_n_wg && DEVICES_INFO[0].n_wi_wg == DEVICES_INFO[0].def_n_wi_wg) {
					n_strs = SS_CPU * DEVICES_INFO[0].compute_units;
4d26a735   Pedro Roque   Increased recogni...
1978
1979
				} else {
					n_strs = (unsigned int)((DEVICES_INFO[0].n_wg * DEVICES_INFO[0].n_wi_wg * SS_CPU * DEVICES_INFO[0].compute_units) /
94b2b13d   Pedro Roque   PHACT source
1980
1981
							(DEVICES_INFO[0].def_n_wg * DEVICES_INFO[0].def_n_wi_wg));
				}
4d26a735   Pedro Roque   Increased recogni...
1982
			}
94b2b13d   Pedro Roque   PHACT source
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996

			// cap on 1.000.000 per device
			if (n_strs > MAX_SS) {
				n_strs = MAX_SS;
			}

		} else {
			n_strs = N_SS;
		}

		// calculate the depth of the tree needed to expand
		*n_ss = 1;
		*depth = 0;
		i = 0;
4d26a735   Pedro Roque   Increased recogni...
1997
		while ((*n_ss) < n_strs && vs_to_label_cntr < n_vs_to_label) {
94b2b13d   Pedro Roque   PHACT source
1998
1999
			if (VS[i].to_label) {
				(*n_ss) *= VS[i].n_vals;
4d26a735   Pedro Roque   Increased recogni...
2000
				EXP_VALUES[i] = VS[i].n_vals;
94b2b13d   Pedro Roque   PHACT source
2001
2002
2003

				// will be fully expanded during sub-search spaces creation, so its already labeled
				VS[i].to_label = false;
4d26a735   Pedro Roque   Increased recogni...
2004
				VS[i].expanded = true;
94b2b13d   Pedro Roque   PHACT source
2005
2006
2007
2008
				vs_labeled_at_exp++;
				vs_to_label_cntr++;

			} else {
4d26a735   Pedro Roque   Increased recogni...
2009
				EXP_VALUES[i] = 1;
94b2b13d   Pedro Roque   PHACT source
2010
2011
2012
2013
			}

			(*depth)++;
			i++;
4d26a735   Pedro Roque   Increased recogni...
2014
		}
94b2b13d   Pedro Roque   PHACT source
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

		// if expanding all the tree nodes to depth generate more than the required number of sub-search spaces
		if ((*n_ss) != n_strs) {
			i--;
			(*n_ss) /= VS[i].n_vals;

			// reset, because it will not be fully expanded
			VS[i].to_label = true;
			VS[i].expanded = false;
			vs_labeled_at_exp--;
			vs_to_label_cntr--;

			for (j = 2; j < VS[i].n_vals; j++) {
				if ((*n_ss) * j >= n_strs) {
4d26a735   Pedro Roque   Increased recogni...
2029
					(*n_ss) *= j;
94b2b13d   Pedro Roque   PHACT source
2030
2031
2032
					EXP_VALUES[i] = j;
					break;
				}
4d26a735   Pedro Roque   Increased recogni...
2033
			}
94b2b13d   Pedro Roque   PHACT source
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
			if (j == VS[i].n_vals) {
				(*n_ss) *= VS[i].n_vals;
				EXP_VALUES[i] = VS[i].n_vals;
				VS[i].to_label = false;
				VS[i].expanded = true;
				vs_labeled_at_exp++;
				vs_to_label_cntr++;
			}
		}

#if SS_MULTIPLIER
4d26a735   Pedro Roque   Increased recogni...
2045
		unsigned long long mult_max_aux = 1;
94b2b13d   Pedro Roque   PHACT source
2046
2047
2048
2049
2050
2051
2052
2053
2054
		// get the max multiplier that can be applied to the number of ss inside each device
		if (*depth != N_VS) {
			for (i = (*depth); i < N_VS && vs_to_label_cntr < n_vs_to_label && mult_max_aux * (*n_ss) < UINT_MAX; i++) {
				if (VS[i].n_vals > 1 && VS[i].to_label) {
					vs_to_label_cntr++;
					mult_max_aux *= VS[i].n_vals;
				}
			}
			if (mult_max_aux * (*n_ss) > UINT_MAX) {
4d26a735   Pedro Roque   Increased recogni...
2055
				if (i == N_VS) {
94b2b13d   Pedro Roque   PHACT source
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
					i--;
				}
				mult_max_aux /= VS[i].n_vals;

				for (j = 2; j < VS[i].n_vals; j++) {
					if (mult_max_aux * (*n_ss) * j > UINT_MAX) {
						j--;
						mult_max_aux *= j;
						break;
					}
				}
			}
			mult_max = (unsigned int)mult_max_aux;
		}
		if (mult_max == 0) {
			mult_max = 1;
		}
#else
		mult_max = 1;
#endif
	}
}
4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source

4d26a735   Pedro Roque   Increased recogni...

94b2b13d   Pedro Roque   PHACT source