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