我需要使用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中?
问候!
修改
这是分层聚类算法的一部分,如上所述:
答案 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()
的最后一个参数。