使用pthread和信号量

时间:2016-06-14 17:00:16

标签: c pthreads semaphore

我需要使用pthreads和信号量并行使这个代码并行工作。它最多可以使用16个线程。

这是以串行方式工作的代码:

    for(counter = numberOfPoints; counter > numberOfClusters; counter--){

        double minimunValue = 9999999999999;

        for(i = 0; i < counter; i++){
            for(j = 0; j < counter; j++){
                if((distanceMatrix[i][j] < minimunValue) && (i != j)){

                    minimunValue = distanceMatrix[i][j];
                    cityA = i;
                    cityB = j;
                }
            }
        }


        for(j = 0; j < counter; j++){
            if(j == cityA) 
                distanceMatrix[cityA][j] = 0;

            if(distanceMatrix[cityA][j] > distanceMatrix[cityB][j]){
                distanceMatrix[cityA][j] = distanceMatrix[cityB][j];
                distanceMatrix[j][cityA] = distanceMatrix[cityB][j];
            }
        }


        for(i = 0; i < counter; i++){
            for(j = cityB; j < counter - 1; j++){
                distanceMatrix[i][j] = distanceMatrix[i][j+1];
            }
        }

        for(i = cityB;i < (counter-1);i++){
            distanceMatrix[i] = distanceMatrix[i+1];  

        }
        //more code here but it doesn't matter for now
    }

我做了什么:

我创建了两个这样的信号量:

sem_t* mutex;
sem_t* lock;

    //inside main()
    int rc = sem_unlink("mutex");
    if (rc)
        perror("sem_unlink mutex");

    rc = sem_unlink("barrier");
    if (rc)
        perror("sem_unlink barrier");

    numberOfClusters = atoi(argv[2]);
    numberOfThreads = atoi(argv[3]);

    mutex = sem_open("mutex", O_CREAT, S_IRUSR | S_IWUSR, numberOfThreads);
    lock = sem_open("barrier", O_CREAT, S_IRUSR | S_IWUSR, numberOfThreads);

我按如下方式实施了障碍:

void barrier() {
    sem_wait(mutex);
    if (threadsWorking == (numberOfThreads - 1)) {
        threadsWorking = 0;
        sem_post(mutex);

        int i;
        for (i = 0; i < (numberOfThreads - 1); i++) {
            sem_post(lock);
        }
    } else {
        threadsWorking++;
        sem_post(mutex);
        sem_wait(lock);
    }
}  

现在,将在每个线程上调用的函数:

void *thread_clustering(void *thread_id){
    int i, j;
    int thread_counter = thread_id;

    //this is the 2nd for, this part is working fine using pthreads
    for(i = thread_counter; i < counter; i += numberOfThreads){
        if(distanceMatrix[cityA][i] > distanceMatrix[cityB][i]){
            distanceMatrix[cityA][i] = distanceMatrix[cityB][i];
            distanceMatrix[i][cityA] = distanceMatrix[cityB][i];
        }
    }

    barrier();

    //this commented code is about the 3rd for, but it is not working as I want
    // for(i = thread_counter; i < counter; i += numberOfThreads){
    //     for(j = cityB; j < counter - 1; j++){
    //         distanceMatrix[i][j] = distanceMatrix[i][j+1];
    //     }
    // }

    // barrier();
}

这就是我认为我的最终代码将在所有并行化之后的方式:

for(counter = numberOfPoints; counter > numberOfClusters; counter--){
    for(i = 0; i < numberOfThreads; i++){
        pthread_create(&threads[i],NULL, thread_clustering, (void *)i);
    }  

    for(i = 0; i < numberOfThreads; i++){
        pthread_join(threads[i], NULL);
    } 
    //more code here
}

所以,任何人都知道如何将所有第一个代码放在thread_clustering中?

问候!

修改

这是分层聚类算法的一部分,如上所述:

  1. 从包含一个对象的n个群集开始
  2. 从邻近区域找到最相似的一对簇Ci和Cj 矩阵并将它们合并为一个集群
  3. 更新邻近矩阵(通过用合并的群集替换各个群集,将其顺序​​减少一个)
  4. 重复步骤(2)e(3)直到获得单个簇(即N-1次)

1 个答案:

答案 0 :(得分:0)

对于第一组嵌套for()循环,它找到最近的一对城市,它很容易以与其他循环相同的方式并行化,以便每个线程找到最接近的在其搜索部分内的一对城市:

double minimumValue = DBL_MAX;

for (i = thread_counter; i < counter; i += numberOfThreads) {
    for (j = 0; j < counter; j++) {
        if ((distanceMatrix[i][j] < minimumValue) && (i != j)) {
            minimumValue = distanceMatrix[i][j];
            cityA = i;
            cityB = j;
        }
    }
}

但是对于函数的其余部分,您需要在所有线程中使用最接近的城市集。所以,你需要一个&#34;最接近的城市&#34;数组,每个线程一个,并在第一个循环后让每个线程存储到该数组中:

closest[thread_counter].distance = minimumValue;
closest[thread_counter].cityA = cityA;
closest[thread_counter].cityB = cityB;

现在你需要等待其他线程存储它们的值,然后选择最小的线程:

barrier();

minimumValue = DBL_MAX;

for (i = 0; i < numberOfThreads; i++) {
    if (minimumValue > closest[i].distance) {
        minimumValue = closest[i].distance)
        cityA = closest[i].cityA;
        cityB = closest[i].cityB;
    }
}

(请注意,我们需要再次将minimumValue重新设置为最大值,以便所有线程始终以相同的顺序选择相同的城市对,如果有多个选项具有相同的距离)。

请注意,您的barrier()实现存在问题 - 您应该将mutex信号量初始化为值1(以便只有等待它的第一个线程可以继续执行,直到它应该将lock信号量初始化为值0(以便等待它的所有线程都被阻止,直到它被发布)。信号量的初始值是sem_open()的最后一个参数。