Witam,

Zauważyłem dziwne zachowanie funkcji z mojego programu który zrównoleglony jest za pomocą openMP. Funkcja ta ma za zadanie rozdzielenie ciągu liczb na ilość podanych podciągów. Poniżej kod funkcji

void splitSequence (int thNums, int seqLen, int *seq, int *splitSeqLen, int **splitSeq)
{
	int i, j;
	int singleSeqLen = seqLen / thNums;
	int seqMod = seqLen % thNums;
	
	for (i = 0; i < thNums; i++)
		splitSeqLen[i] = singleSeqLen;
	
	for (i = thNums - 1; i >= thNums - seqMod; i--)
		splitSeqLen[i]++;
		
	printf("\n 1 \n");	
	for (i = 0; i < thNums; i++)
		printf("\nsplitSeqLen %d \n", splitSeqLen[i]);
		
	for (i = 0, j = 0; j < thNums; i+=splitSeqLen[j], j++)
		splitSeq[j] = &seq[i];
	
	printf("\n 2 \n");
	for (i = 0; i < thNums; i++)
		printf("\nsplitSeqLen %d \n", splitSeqLen[i]);
}

Powyższy kod skompilowany wykonany na moim komputerze (4 rdzenie - rozdzielenie ciągu na 4 podciągi) - dystrybucja ubuntu 64 bit daje poprawne wyniki.
Dla ciągu o długości 10 liczb

1
splitSeqLen 2
splitSeqLen 2
splitSeqLen 3
splitSeqLen 3

2
splitSeqLen 2
splitSeqLen 2
splitSeqLen 3
splitSeqLen 3

natomiast kod skompilowany i wykonany na zdalnej maszynie 16 rdzeniowej z procesorami o architekturze x86-64 z systemem operacyjnym fedora daje niepoprawny wynik przy wyjściu z funkcji

Dla ciągu o długości 10 liczb i rozdzielony na 5 podciągów

1
splitSeqLen 2
splitSeqLen 2
splitSeqLen 2
splitSeqLen 2
splitSeqLen 2

2
splitSeqLen 33447984
splitSeqLen 0
splitSeqLen 2
splitSeqLen 2
splitSeqLen 2

Między dwoma wyświetleniami tablica splitSeqLen nie jest modyfikowana więc nie mam pojęcia skąd bierze się ta różnica...

Poniżej umieszczam cały kod programu do wglądu


#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <omp.h>

int compare (int *, int , int *);
void splitSequence (int , int, int *,int *, int **);
void mergeSequences (int , int , int *, int *, int **);
void displaySequence (int *, int);
void saveResult (int *, int, int, double, FILE*);

int main()
{
	int i, j, k, seqLen, seed, thNums, temp;
	int *seq;															// array of sequence numbers
	int *sortedSeq;														// array of sorted numbers
	int **splitSeq;														// array of pointers of splitted sequences
	int *splitSeqLen;													// array of splitted sequences' length									
	clock_t start, stop;
	FILE *fp;
	double execTime;
	char c;
	
	printf("Please enter sequence length : ");
	scanf("%i", &seqLen);
	printf("Please enter number of threads (max 16) : ");
	scanf("%i", &thNums);
	
	seq = (int *)malloc(seqLen * sizeof(*seq));							// dynamically allocate memory for sequance array
	sortedSeq = (int *)malloc(seqLen * sizeof(*seq));					// dynamically allocate memory for sorted numbers array
	splitSeq = (int **)malloc(thNums * sizeof(**splitSeq));				// dynamically allocate memory for splitted seq array
	splitSeqLen = (int *)malloc(thNums * sizeof(*splitSeqLen));			// dynamically allocate memory for splitted seq length array
	
	if (seq == NULL || splitSeq == NULL || splitSeqLen == NULL)
	{
        printf("Memory allocation error");
        return -1;        
    }  
     
	seed = time(NULL);													// set randomization
	srand(seed);
	
	for (i = 0; i < seqLen; i++)										// get random numbers
		seq[i] = rand();
	
    //printf("\nDisplay randomized numbers ? (y\\n) : ");
	//scanf("%s", &c);
	
	//if (c == 'y')
	//	displaySequence(seq, seqLen);
	
	omp_set_num_threads(thNums);
	splitSequence(thNums, seqLen, seq, splitSeqLen, splitSeq);
	start = clock();
	printf("\nStart mp\n");
#pragma omp parallel private(i, j, k, temp) \
			firstprivate(splitSeqLen, thNums, splitSeq)		
	{	
#pragma omp for schedule(static)
		for (i = 0; i < thNums; i++)
		{
			printf("Thread number %d has stared sorting...\n",
					omp_get_thread_num());
			for (j = 0; j < splitSeqLen[i] - 1; j++)
			{
				for (k = 0; k < splitSeqLen[i] - 1 - j; k++)
				{
					if(splitSeq[i][k] > splitSeq[i][k+1])
					{
						temp =  splitSeq[i][k];
						splitSeq[i][k] = splitSeq[i][k+1];
						splitSeq[i][k+1] = temp;       
					} 
				}
			}
			printf("Thread number %d has finished sorting...\n",
					omp_get_thread_num());
		}
	}
	stop = clock();
	execTime = ((double) stop-start) / CLOCKS_PER_SEC;
	printf("\nSorting time - ");
	printf("%f", execTime);
	
	start = clock();
	mergeSequences(thNums, seqLen, sortedSeq, splitSeqLen, splitSeq);
	stop = clock();
	execTime = ((double) stop-start) / CLOCKS_PER_SEC;
	
	printf("\nMerging time - ");
	printf("%f", execTime);
	printf("\n\nWhat do you want ? :\n");
	printf("- Press 1 for saving results.\n");
	printf("- Press 2 for displaying results.\n");
	printf("- Press any other key for exit.\n");
	scanf("%s", &c);
	
	switch (c)
	{
		case '1':
			saveResult(sortedSeq, seqLen, thNums, execTime, fp);
			break;
		case '2':
			displaySequence(sortedSeq, seqLen);
			break;
		default :
			break;
	}
	
	free(seq);
	free(sortedSeq);
	free(splitSeq);
	free(splitSeqLen);
	
	return 0;
}

void splitSequence (int thNums, int seqLen, int *seq, int *splitSeqLen, int **splitSeq)
{
	int i, j;
	int singleSeqLen = seqLen / thNums;
	int seqMod = seqLen % thNums;
	
	for (i = 0; i < thNums; i++)
		splitSeqLen[i] = singleSeqLen;
	
	for (i = thNums - 1; i >= thNums - seqMod; i--)
		splitSeqLen[i]++;
		
	printf("\n 1 \n");	
	for (i = 0; i < thNums; i++)
		printf("\nsplitSeqLen %d \n", splitSeqLen[i]);
		
	for (i = 0, j = 0; j < thNums; i+=splitSeqLen[j], j++)
		splitSeq[j] = &seq[i];
	
	printf("\n 2 \n");
	for (i = 0; i < thNums; i++)
		printf("\nsplitSeqLen %d \n", splitSeqLen[i]);
}

void mergeSequences (int thNums, int seqLen, int *sortedSeq, int *splitSeqLen, int **splitSeq)
{
	int i, j, index;
	int indexes[thNums];
	int *comparedNums = (int *)malloc(thNums * sizeof(*comparedNums));
	
	for (i = 0; i < thNums; i++)
		indexes[i] = 0;
		
	for (i = 0; i < seqLen; i++)
	{
		
		for (j = 0; j < thNums; j++)
			comparedNums[j] = splitSeq[j][indexes[j]];
			
		index = compare(comparedNums, thNums, &sortedSeq[i]);
		
		if (indexes[index] < splitSeqLen[index]-1)
			indexes[index]++;
		else
			splitSeq[index][indexes[index]] = -1;	
	}
	
	free(comparedNums);
}

int compare (int *comparedNums, int thNums, int *min)
{
	int i, index;
	for (i = 0; i < thNums; i++)
	{
		if (comparedNums[i] >= 0)
		{
			*min = comparedNums[i];
			index = i;
			break;
		}
	}
			
	for (i = 0; i < thNums; i++)
	{
		if (comparedNums[i] <= *min && comparedNums[i] >= 0)
		{
			*min = comparedNums[i];
			index = i;
		}
	}
	
	return index;
}

void displaySequence (int *seq, int seqLen)
{
	int i;
	printf("\n");
	for (i = 0; i < seqLen; i++)
	{
		printf("%d", seq[i]);
        printf("\n");
	} 
}

void saveResult (int *seq, int seqLen, int thNums, double execTime, FILE *fp)
{
	int i;
	struct tm *ptr;
	char str[100];
	time_t timeValue;
	timeValue = time(NULL);
	ptr = localtime(&timeValue);
	strftime(str, 100, "%c", ptr);
	fp=fopen(str,"w");
	fprintf(fp,"<<<<< STATISTICS >>>>> \n");
	fprintf(fp,"Sequence length : %d\n", seqLen);
	fprintf(fp,"Used threads : %d\n", thNums);
	fprintf(fp,"Sorting time : %f\n", execTime);
	fprintf(fp,"<<<<< SEQUENCE >>>>> \n");
	
	for (i = 0; i < seqLen; i++)
		fprintf(fp,"%d\n", seq[i]);
}

Pozdrawiam,
Patryk