/* Bn(полуочиститель, half - cleaner) над массивом, параллельно
упорядочивающая элементы пар xi и xi + half */
void Bn (long *elements, int k, int direction) {
	int i;
	for(i = 0; i<(1<<k) ; i++) {
		if (direction*asc_order(&elements[i],&elements[i+(1<<k)]) > 0) {
			exchange(&elements[i],&elements[i+(1<<k)]);
		}
	}
}
Exemple #2
0
void		put_in_order(t_tetris *list)
{
  t_tetris	*it;
  int		not_yet;

  not_yet = 1;
  while (not_yet == 1)
    {
      not_yet = 0;
      it = list->next;
      while (it != list && it->next != list)
	{
	  if (asc_order(it->name, it->next->name) == 1)
	    {
	      exchange_elems(it, it->next);
	      not_yet = 1;
	    }
	  it = it->next;
	}
    }
}
int main(int argc, char *argv[]) 
{ 
	int n;         /* Размер сортируемого массива */ 
	int nrank;      /* Общее количество процессов */ 
	int myrank;    /* Номер текущего процесса */ 
	long *elements;   /* Массив элементов, хранимые локально */ 
	long ** bucket;   /* Массив корзин, хранимые локально */ 
	int *size;   /* Массив размеров корзин */ 
	int *bucketid;   /* Идентификатор корзины */ 
	int direction; /* Порядок сортировки 1 - по возрастанию, -1 по убыванию */
	int len; /* Параметр для индексатора */
	int index; /* Параметр для индексатора */
	int nbucket; /* Количество корзин на одном процессе */ 
	int i, j, k, m, id, x; 
	MPI_Status status; 
	char *inputFileName;
	char *outputFileName;

	/* Иницилизация MPI */
	MPI_Init(&argc, &argv);
	MPI_Comm_size(MPI_COMM_WORLD, &nrank);
	MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

	if (myrank == 0 && argc < 2){
		printf("Usage :\t%s <inputfile> <outputfile>\n", argv[0]); fflush(stdout);
	}

	if (argc < 2){
		MPI_Finalize();
		exit(-1);
	}

	// Получаем параметры - имена файлов
	inputFileName = argv[1];
	outputFileName = argv[2];

	// Подсчитываем количество элементов в файле
	if (myrank == 0){
		FILE *fl = fopen(inputFileName, "r");
		n = 0;
		long v;
		while (fscanf(fl,"%ld", &v)==1) n++;
		fclose(fl);
	}
	MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

	// Устанавливаем сортировку по-возрастанию
	direction = 1;

	len = 0; while ((1 << (++len))<n); len = (int)((len + 1) / 2);
	index = 8*sizeof(int)-len;
	nbucket = (int)((1<<len)+nrank-1)/nrank;

	elements  = (long *)malloc(n*sizeof(long)); 

	if (myrank == 0) {

		printf("Title :\t%s\n", title);
		printf("Description :\t%s\n", description);
		printf("Number of processes :\t%d\n", nrank);
		printf("Array size :\t%d\n", n);
		printf("Indexator :\t%d %d\n", index, len);
		printf("Number of buckets per process :\t%d\n", nbucket);
		printf("Input file name :\t%s\n", inputFileName);
		printf("Output file name :\t%s\n", outputFileName);

		/* Заполняем массив числами */
		/* Операция выполняется только на ведущем процессе */
		FILE *fl = fopen(inputFileName, "r");
		for (i = 0; i<n; i++) {
			fscanf(fl, "%ld", &elements[i]);
		}
		fclose(fl);
	}

	bucket = (long**)malloc(nbucket*sizeof(long*));
	size = (int*)malloc(nbucket*sizeof(int));
	bucketid = (int*)malloc(nbucket*sizeof(int));

	for(j=0; j<nbucket ; j++) {
		bucket[j] = (long*)malloc(n*sizeof(long));
	}

	nbucket = 0;

	while(n--) {
		if (myrank == 0) {
			x = elements[n];
		}

		MPI_Bcast(&x, 1, MPI_LONG, 0, MPI_COMM_WORLD);
		id = indexator(&x,index,len); /* Определяем номер корзины */
		if (id%nrank == myrank) {
			/* Если корзина обслуживается данным процессом, то процесс добавляет элемент в корзину */
			j = nbucket; while (j-- && bucketid[j]!=id);
			if (j==-1) { size[nbucket]=0; bucketid[nbucket] = id; bucket[nbucket][size[nbucket]++] = x; nbucket++; } 
			else bucket[j][size[j]++] = x;
		}
	}

	/* Сортируем каждую корзину в отдельности */

	for(i=0; i< nbucket ;i++) {
		qsort(bucket[i],size[i],sizeof(long),((direction>0)?asc_order:desc_order));
	}

	/* Собираем корзины вместе в соответсвии с порядком сортировки */

	n=0;

	for(k = 0; k < (1<<len) ; k++) {
		id = (direction>0)?k:((1<<len)-k-1);
		i = id%nrank; /* Определяем номер процесса хранящего корзину */
		j = nbucket; while ((j--) && (bucketid[j]!=id));
		if (myrank == i && myrank == 0 && j != -1) { /* Если корзина на главном процессе */
			copy(&elements[n], bucket[j], size[j]);
			n += size[j];
		} 
		else if (myrank == i && myrank > 0 && j != -1) {
			MPI_Send(&size[j], 1, MPI_INT, 0, DATA_TAG, MPI_COMM_WORLD); /* Уведомляем о количестве передаваемых данных */
			MPI_Send(bucket[j], size[j], MPI_LONG, 0, DATA_TAG, MPI_COMM_WORLD);
		}
		else if (myrank == i && myrank > 0 && j == -1) {
			int zero = 0;
			MPI_Send(&zero, 1, MPI_INT, 0, 1, MPI_COMM_WORLD); /* Уведомляем о количестве передаваемых данных */
		}
		else if (myrank != i && myrank == 0 && nrank > 1) {
			MPI_Recv(&m, 1, MPI_INT, i, DATA_TAG, MPI_COMM_WORLD, &status);
			if (m>0) MPI_Recv(&elements[n], m, MPI_LONG, i, DATA_TAG, MPI_COMM_WORLD, &status);
			n += m;
		}
	}


	/* Проверяем и выводим результаты */
	if (myrank == 0) {
		int check = 1;
		for(i=1; i<n && check==1 ;i++) {
			check = (direction*asc_order(&elements[i-1],&elements[i]) <= 0)?1:0;
		}

		printf("Array size :\t%d\n", n);
		printf("Check :\t%s\n", (check?"ok":"fail"));

		FILE *fl = fopen(outputFileName, "w");
		for (i = 0; i<n; i++) {
			fprintf(fl, "%ld\n", elements[i]);
		}
		fclose(fl);
	}

	/* Освобождаем ранее выделенные ресурсы */

	for(i=0; i<nbucket ; i++) {
		free(bucket[i]);
	}

	free(bucket);
	free(bucketid); 
	free(size); 
	free(elements); 

	MPI_Finalize(); 
	exit(0);
}