Exemple #1
0
bucket_t* bucket_init(unsigned int node_capacity)
{
	bucket_t* bucket;
	bool error = false;
	
	/* Capacity must strictly be a positive number */
	
	if(node_capacity == 0)
	{
		fprintf(stderr, "bucket_init: Invalid capacity");
		error = true;
	}
	
	/* Allocate memory for the bucket */
	
	if(!error && (bucket = malloc(sizeof(struct bucket_struct))) == NULL)
	{
		perror("bucket_init");
		error = true;
	}
	
	/* Initialize all bucket's fields */
	
	if(!error)
	{
		bucket->size = 0;
		bucket->last_node_size = 0;
		bucket->node_capacity = node_capacity;
		bucket->chain = NULL;
	}
	
	/* If an error occured, free any allocated memory */
	
	if(error)
		bucket_destroy(&bucket);
	
	return bucket;
}
/*
 * Bucket-sort algorithm.
 */
extern void bucketsort(int *array, int n)
{
	int max;                  /* Maximum number.      */
	int i, j;                 /* Loop indexes.        */
	int range;                /* Bucket range.        */
	struct minibucket *minib; /* Working mini-bucket. */
	struct message *msg;      /* Working message.     */
	struct bucket **todo;     /* Todo buckets.        */
	struct bucket **done;     /* Done buckets.        */
	uint64_t start, end;      /* Timers.              */
	
	/* Setup slaves. */
	open_noc_connectors();
	spawn_slaves();
	sync_slaves();
	
	todo = smalloc(NUM_BUCKETS*sizeof(struct bucket *));
	done = smalloc(NUM_BUCKETS*sizeof(struct bucket *));
	for (i = 0; i < NUM_BUCKETS; i++)
	{
		done[i] = bucket_create();
		todo[i] = bucket_create();
	}

	/* Find max number in the array. */
	start = timer_get();
	max = INT_MIN;
	for (i = 0; i < n; i++)
	{
		/* Found. */
		if (array[i] > max)
			max = array[i];
	}

	/* Distribute numbers. */
	range = max/NUM_BUCKETS;
	for (i = 0; i < n; i++)
	{
		j = array[i]/range;
		if (j >= NUM_BUCKETS)
			j = NUM_BUCKETS - 1;
		
		bucket_insert(&todo[j], array[i]);
	}
	end = timer_get();
	master += timer_diff(start, end);

	/* Sort buckets. */
	j = 0;
	for (i = 0; i < NUM_BUCKETS; i++)
	{	
		while (bucket_size(todo[i]) > 0)
		{
			minib = bucket_pop(todo[i]);
			
			/* Send message. */
			msg = message_create(SORTWORK, i, minib->size);
			message_send(outfd[j], msg);
			message_destroy(msg);
			
			/* Send data. */
			communication += 
				data_send(outfd[j], minib->elements, minib->size*sizeof(int));
			minibucket_destroy(minib);
			
			j++;
			
			/* 
			 * Slave processes are busy.
			 * So let's wait for results.
			 */
			if (j == nclusters)
			{	
				/* Receive results. */
				for (/* NOOP */ ; j > 0; j--)
				{					
					/* Receive message. */
					msg = message_receive(infd[nclusters - j]);
					
					/* Receive mini-bucket. */
					minib = minibucket_create();
					minib->size = msg->u.sortresult.size;
					communication += data_receive(infd[nclusters -j], minib->elements, 
													minib->size*sizeof(int));
					
					bucket_push(done[msg->u.sortresult.id], minib);
					
					message_destroy(msg);
				}
			}
		}
	}

	/* Receive results. */
	for (/* NOOP */ ; j > 0; j--)
	{						
		/* Receive message. */
		msg = message_receive(infd[j - 1]);
					
		/* Receive bucket. */
		minib = minibucket_create();
		minib->size = msg->u.sortresult.size;
		communication += 
			data_receive(infd[j - 1], minib->elements, minib->size*sizeof(int));
					
		bucket_push(done[msg->u.sortresult.id], minib);
					
		message_destroy(msg);
	}

	start = timer_get();
	rebuild_array(done, array);
	end = timer_get();
	master += timer_diff(start, end);
	
	/* House keeping. */
	for (i = 0; i < NUM_BUCKETS; i++)
	{
		bucket_destroy(todo[i]);
		bucket_destroy(done[i]);
	}
	free(done);
	free(todo);
	join_slaves();
	close_noc_connectors();
}
Exemple #3
0
bucket_t* bucket_split(bucket_t* bucket1, bool (*split_funct)(void* data, unsigned int key), void* data)
{
	assert(bucket1 != NULL && split_funct != NULL);
	
	unsigned int i;
	unsigned int curr_node_size;
	bool error = false;
	
	bucket_t* bucket2 = NULL;
	bucket_t** dst_bucket_ptr = NULL;
	
	bucket_t* src_bucket = NULL;
	bucket_node_t* src_bucket_node = NULL;
	
	/* Allocate memory for the new bucket */
	
	if(!error && (bucket2 = bucket_init(bucket1->node_capacity)) == NULL)
		error = true;
	
	/* Make a copy of the old bucket's head */
	
	if((src_bucket = bucket_init(bucket1->node_capacity)) == NULL)
		error = true;
	
	if(!error)
	{
		/* Move internal data from the old bucket' head to the new
		   bucket head. No deep copy is done, the chain is moved too. */
		
		*src_bucket = *bucket1;
		
		/* Reset the given bucket's head */
		
		*bucket1 = *bucket2;
		
		/* Initialize src_bucket_node */
		
		src_bucket_node = src_bucket->chain;
	}
	
	/* For every bucket_node in the chain... */
	
	while(!error && src_bucket_node != NULL)
	{
		/* Get the current bucket_node's size */
		
		curr_node_size = bucket_node_size(src_bucket, src_bucket_node);
		
		/* For every entry in the bucket_node... */
		
		for(i=0; !error && i < curr_node_size; i++)
		{
			/* Call split_funct to get the target bucket */
			
			if(!(*split_funct)(data, src_bucket_node->key[i]))
				dst_bucket_ptr = &bucket1;
			else
				dst_bucket_ptr = &bucket2;
			
			/* Append to the appropriate new bucket (entries are already sorted) */
			
			if(!bucket_node_insert(*dst_bucket_ptr, bucket_size(*dst_bucket_ptr), src_bucket_node->key[i], src_bucket_node->value[i]))
				error = true;
		}
		
		src_bucket_node = src_bucket_node->overflow;
	}
	
	if(error)
	{
		/* Restore the old bucket in its original condition */
		
		*bucket1 = *src_bucket;
		
		/* Free allocated memory */
		
		bucket_destroy(&bucket2);
		
		/* Prevent old bucket chain from being destroyed */
		
		src_bucket->chain = NULL; 
	}
	
	/* Destroy the old bucket */
	
	bucket_destroy(&src_bucket);
	
	return bucket2;
}
int vos_process_create(struct Stmt *create)
{
	int			i		= 0;
	int			s		= 0;
	int			n_in		= 0;
	int			n_done		= 0;
	int			n_bucket	= 1;
	struct File		*F		= 0;
	struct StmtMeta		*pin		= create->in;
	struct ProcCreate	*cproc		= 0;
	struct Bucket		*buckets	= 0;
	struct Field		*fld		= 0;

	/* how many input ? */
	while (pin) {
		n_in++;
		pin = pin->next;
	}

	/* how many field output (bucket) ? */
	fld = create->out->fields;
	while (fld) {
		n_bucket++;
		fld = fld->next;
	}

	s = file_open(&F, create->out->filename, FOPEN_WO);
	if (s)
		goto err;

	cproc = (struct ProcCreate *) calloc(n_in, sizeof(struct ProcCreate));
	if (! cproc) {
		s = E_MEM;
		goto err;
	}

	buckets = (struct Bucket *) calloc(n_bucket, sizeof(struct Bucket));
	if (! buckets) {
		s = E_MEM;
		goto err;
	}

	pin = create->in;
	for (i = 0; i < n_in; i++) {
		stmt_update_meta(create->prev, pin);

		cproc[i].in		= pin;
		cproc[i].status		= CPROC_START;
		cproc[i].buckets	= buckets;

		pthread_create(&cproc[i].tid, 0, create_process,
				(void *) &cproc[i]);
		pin = pin->next;
	}

	/* phase 1: create & fill bucket */
	for (i = 0; i < n_in; i++) {
		/* wait until child fill the buckets */
		while (cproc[i].status == CPROC_START)
			sleep(THREAD_TIME_WAIT);

		if (cproc[i].status == CPROC_DONE) {
			pthread_join(cproc[i].tid, 0);
			if (cproc[i].retval) {
				s = cproc[i].retval;
				goto err;
			}

			n_done++;
			cproc[i].status	= CPROC_END;
		}
	}

	if (_vos.debug & DBG_CREATE) {
		printf("parent: writing bucket\n");
	}
	s = bucket_write(buckets, n_bucket, F, create->out->fields);
	if (s)
		goto err;

	/* phase 2: fill the buckets */
	while (n_done < n_in) {
		for (i = 0; i < n_in; i++) {
			/* restart threads */
			if (cproc[i].status == CPROC_BUCKETS_FULL)
				cproc[i].status = CPROC_START;
		}

		for (i = 0; i < n_in; i++) {
			/* wait until child fill the buckets */
			while (cproc[i].status == CPROC_START)
				sleep(THREAD_TIME_WAIT);

			if (cproc[i].status == CPROC_DONE) {
				pthread_join(cproc[i].tid, 0);

				/* catch error here */
				if (cproc[i].retval) {
					s = cproc[i].retval;
					goto err;
				}

				n_done++;
				cproc[i].status	= CPROC_END;
			}
		}

		if (_vos.debug & DBG_CREATE) {
			printf("parent: writing bucket\n");
		}
		s = bucket_write(buckets, n_bucket, F, create->out->fields);
		if (s)
			goto err;
	}

err:
	if (s && cproc) {
		/* cancel all thread */
		for (i = 0; i < n_in; i++) {
			if (cproc[i].status == CPROC_BUCKETS_FULL) {
				cproc[i].status	= CPROC_DONE;
				pthread_join(cproc[i].tid,
						(void *) &cproc[i].retval);
			}
		}
	}

	bucket_destroy(buckets, n_bucket);

	if (buckets)
		free(buckets);
	if (cproc)
		free(cproc);
	if (F)
		file_close(&F);
	return s;
}