我正在做一个与使用多个线程进行并行快速排序有关的功课,由于以下困难,我没有按时完成这项功课。但是,我仍然想弄清楚问题。
基本上,我正在尝试将作品分配给子线程并控制它们何时应该通过sem_post开始工作,它们的初始值为0的当前信号量(当然,子项首先等待它们的0值信号量)。
然而,有时线程2或3(我创建了14个子线程)在线程0 sem_post之前唤醒了它们首先sem_wait的信号量,而有时它们像我认为的那样工作(从等待中删除后唤醒)从指定的线程中通过sem_post排队。)
(已编辑)每个帖子正在做什么的详细说明:
母线程创建14个子线程和14个信号量值0.每个线程都有自己的专用信号量,可以通过传递给线程的索引作为参数引用(我知道它很复杂,但我不知道该怎么做简明扼要地说)。首先,所有子线程sem_wait自己的信号量等待工作。 接下来,母线程通过快速排序将输入数组分区为subArray1和subArray2,其中subArray1<枢轴< subArray2,然后sem_post线程0和线程1.此时,母亲调用sem_wait等待剩余排序的完成。 然后,线程0和线程1执行与母线程和sem_post线程2,3,4和5相同的操作,依此类推。直到第四级,线程6~线程13将执行冒泡排序和sem_post母线程以通知最后完成排序。
以下是该计划的主要部分:
typedef struct thread_param th_param;
struct thread_param {
int index;
int front, rear;
};
sem_t* sem[14];
sem_t* finish;
int cnt = 0;
th_param th[14];
vector<int> arr;
void *run_thread(void *index) {
pthread_detach(pthread_self());
int ind = reinterpret_cast<intptr_t>(index);
if(sem_wait(sem[ind]) < 0){ /* <- the thread should wait at here for the appointed thread
calls sem_post toward their semaphore for removing them from waiting queue */
perror("sem_wait");
}
int front = th[ind].front;
int rear = th[ind].rear;
if(front > rear) {
front = rear;
}
int size = rear - front + 1;
int prefix = front;
int pivot = front;
if(ind <= 5 && rear > front) {
pivot = (rand_r(&seed) % size) + front;
iter_swap(arr.begin()+pivot, arr.begin()+rear);
for(int i=front; i<rear; i++) {
if(arr[i] < arr[rear]) {
iter_swap(arr.begin()+i, arr.begin()+prefix);
prefix++;
}
}
iter_swap(arr.begin()+prefix, arr.begin()+rear);
}
switch(ind) {
case 0:
case 1:
do {
th[(ind+1)*2].front = front;
if(prefix > front) {
th[(ind+1)*2].rear = prefix-1;
}else {
th[(ind+1)*2].rear = prefix;
}
if(prefix < rear) {
th[(ind+1)*2+1].front = prefix+1;
}else {
th[(ind+1)*2+1].front = prefix;
}
th[(ind+1)*2+1].rear = rear;
}while((th[(ind+1)*2].rear < -1) || (th[(ind+1)*2].front < -1) || (th[(ind+1)*2+1].rear < -1) || (th[(ind+1)*2+1].front < -1));
/* thread 0/1 wakes 2,3/4,5 up respectively */
sem_post(sem[(ind+1)*2]);
sem_post(sem[(ind+1)*2+1]);
pthread_exit(NULL);
break;
case 2:
do{
th[ind*3].front = front;
if(prefix > front) {
th[ind*3].rear = prefix-1;
}else {
th[ind*3].rear = prefix;
}
if(prefix < rear) {
th[ind*3+1].front = prefix+1;
}else {
th[ind*3+1].front = prefix;
}
th[ind*3+1].rear = rear;
}while(th[ind*3].rear < -1 || th[ind*3+1].rear < -1);
sem_post(sem[ind*3]);
sem_post(sem[ind*3+1]);
pthread_exit(NULL);
break;
case 3:
do {
th[ind*2+2].front = front;
if(prefix > front) {
th[ind*2+2].rear = prefix-1;
}else {
th[ind*2+2].rear = prefix;
}
if(prefix < rear) {
th[ind*3].front = prefix+1;
}else {
th[ind*3].front = prefix;
}
th[ind*3].rear = rear;
}while(th[ind*2+2].rear < -1 || th[ind*3].rear < -1);
sem_post(sem[ind*2+2]);
sem_post(sem[ind*3]);
pthread_exit(NULL);
break;
case 4:
case 5:
do {
th[ind*2+2].front = front;
if(prefix > front) {
th[ind*2+2].rear = prefix-1;
}else {
th[ind*2+2].rear = prefix;
}
if(prefix < rear) {
th[ind*2+3].front = prefix+1;
}else {
th[ind*2+3].front = prefix;
}
th[ind*2+3].rear = rear;
}while(th[ind*2+2].rear < -1 || th[ind*2+3].rear < -1);
sem_post(sem[ind*2+2]);
sem_post(sem[ind*2+3]);
pthread_exit(NULL);
break;
default: /* bubble sort for bottom level */
if(rear > front) {
int temp = 0;
for(int i=front; i<rear; i++) {
for(int j=front; j<rear-temp; j++) {
if(arr[j] > arr[j+1]) {
iter_swap(arr.begin()+j, arr.begin()+j+1);
}
}
temp++;
}
}
cnt++;
if(cnt == 8) {
sem_post(finish);
}
pthread_exit(NULL);
}
}
void multiThread::multi_thread() {
pthread_t tid[14];
int value = 0;
int rc;
/* create and initilize semaphores */
finish = sem_open("./my_sem", O_CREAT, 0666, value);
if(finish == SEM_FAILED) {
perror("sem_open: ");
exit(1);
}
for(int i=0; i<14; i++) {
sem[i] = sem_open("./my_sem", O_CREAT, 0666, value);
if(sem[i] == SEM_FAILED) {
perror("sem_open: ");
exit(1);
}
}
/* create and initialize threads */
for(int i=0; i<14; i++) {
th[i].index = i;
th[i].front = INT_MIN;
th[i].rear = INT_MIN;
rc = pthread_create(tid+i, NULL, run_thread, (void *) i);
if(rc != 0) {
perror("pthread_create: ");
exit(1);
}
}
/* first partition of quick sort */
int size = (int) arr.size();
int pivot = rand_r(&seed) % size;
int prefix = 0;
iter_swap(arr.begin()+pivot, arr.begin()+(size-1));
for(int i=0; i<(size-1); i++) {
if(arr[i] < arr[size-1]) {
iter_swap(arr.begin()+i, arr.begin()+prefix);
prefix++;
}
}
iter_swap(arr.begin()+prefix, arr.begin()+(size-1));
/* assign subarrays to threads */
th[0].front = 0;
if(prefix > 0) {
th[0].rear = prefix-1;
} else {
th[0].rear = prefix;
}
if(prefix < size-1) {
th[1].front = prefix+1;
}else {
th[1].front = prefix;
}
th[1].rear = size-1;
sem_post(sem[0]);
sem_post(sem[1]);
sem_wait(finish);
for(int i=0; i<size; i++) {
cout << arr[i] << " ";
}
cout << endl;
/* close semaphores and unlink path */
for(int i=0; i<14; i++) {
rc = sem_close(sem[i]);
if(rc != 0 ) {
perror("sem_close(): ");
}
}
rc = sem_close(finish);
if(rc != 0 ) {
perror("sem_close(): ");
}
rc = sem_unlink("./my_sem");
if(rc != 0) {
perror("sem_unlink: ");
}
}
这是我第一次在stackoverflow上提问。如果对我有任何建议,请随时评论我的问题。谢谢你的回复!