Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)
Paste
Pasted as Plain Text by ARGHTOS ( 14 years ago )
void hyperqsort(int *list, int size)
{
printf("num threads: %d\n", NUM_T);
int i;
int num_t = NUM_T;
omp_set_num_threads(num_t);
// Each thread has two lists; these are swapped on every iteration
// This is called trading memory for sanity, since I don't want to try it without this :)
List lists[2][NUM_T];
for (i = 0; i < NUM_T; i++)
{
initList(&lists;[0][i], size);
initList(&lists;[1][i], size);
}
// Calculate the number of elements each thread starts with
int thread_e = (int)(ceil((double)size / num_t));
int median[NUM_T/2]; // median values used on each iteration
int level = NUM_T; // current recursion level, represented as number of threads cooperating directly
int cur = 0, buf = 1; // pointers to current and buffer lists; swapped every iteration
#pragma omp parallel
{
int rank = omp_get_thread_num();
int start = rank * thread_e;
List *cur_li = &lists;[cur][rank];
List *buf_li = &lists;[buf][rank];
cur_li->size = MIN(thread_e, size-start); // last thread may have diff start size
buf_li->size = 0;
memcpy(cur_li->list, list + start, cur_li->size * sizeof(int));
seqsort(cur_li->list, 0, cur_li->size-1);
// loop until level = 1, meaning all threads have no one to work with
while (level > 1)
{
int med_rank = rank/level; // index into median table for current thread
// I'm lazy, okay?
int cur_size = cur_li->size;
// if rank % level = 0, this thread should calculate its median
if (rank % level == 0)
median[med_rank] = cur_li->list[cur_size/2];
#pragma omp barrier // points must be found after medians are calculated
// this is an awesome way of figuring out what to send (copy) to where
partition(cur_li->list, cur_size, median[med_rank],
&cur;_li->lo_s, &cur;_li->lo_e,
&cur;_li->hi_s, &cur;_li->hi_e);
#pragma omp barrier // low swap must happen after li and ho points have been found
// low process sends list to high procs
if (rank % level < level/2)
{
int swp_rank = rank+level/2;
List *swp_li = &lists;[buf][swp_rank];
// first, copy low into own swap buffer (redundant but symmetrical to high case)
if (cur_li->lo_s != -1)
{
memcpy(buf_li->list,
cur_li->list,
loSize(cur_li) * sizeof(int));
buf_li->size = loSize(cur_li);
}
// copy high into beginning of partner process list
if (cur_li->hi_e != -1)
{
memcpy(swp_li->list,
cur_li->list + cur_li->hi_s,
hiSize(cur_li) * sizeof(int));
swp_li->size = hiSize(cur_li);
}
}
#pragma omp barrier // high swap must happen after low is completed
// high process sends list to low procs
if (rank % level >= level/2)
{
int swp_rank = rank-level/2;
List *swp_li = &lists;[buf][swp_rank];
// copy high into own list (way easier than doing this in place here)
if (cur_li->hi_e != -1)
{
memcpy(buf_li->list + buf_li->size,
cur_li->list + cur_li->hi_s,
hiSize(cur_li) * sizeof(int));
buf_li->size += hiSize(cur_li);
}
// copy low into high part of partner process lists
if (cur_li->lo_e != -1)
{
memcpy(swp_li->list + swp_li->size,
cur_li->list,
loSize(cur_li) * sizeof(int));
swp_li->size += loSize(cur_li);
}
}
#pragma omp barrier // sort must happen after lists are copied
seqsort(buf_li->list, 0, buf_li->size-1);
#pragma omp single
{
level /= 2; // reduce cooperating thread count
// swap buffer indices
buf ^= 1;
cur ^= 1;
}
#pragma omp barrier
cur_li = &lists;[cur][rank];
buf_li = &lists;[buf][rank];
buf_li->size = 0;
}
}
// doing this sequentially happens to be much easier
int offset = 0;
for (i = 0; i < NUM_T; i++)
{
memcpy(list + offset, lists[cur][i].list, lists[cur][i].size * sizeof(int));
offset += lists[cur][i].size;
}
}
Revise this Paste