Pthread 条件
Pthread conditionals
如有必要,我可以 post 我的代码,但我的问题主要是概念性的。我正在使用线程实现高斯消去法。我有 p 个 pthreads 按列主要顺序在 nxn 矩阵上运行。在任何 p 线程开始对列进行操作之前,必须执行行操作以将该列中具有最大值的行向上移动到对角线上。所以我需要每个线程都等待,然后统一操作。目前,在每一列,每个线程都会检查它的 id,id=0 的线程将执行行操作。我的问题是如何让除 id=0 之外的所有线程等待,然后统一运行。
我试过使用互斥锁和条件。这些似乎不起作用,因为它们将所有访问权限授予单个线程。据我了解,只能通过让线程请求一个已经存在的锁来以这种方式阻塞线程,因此它必须等待。这对我来说是个问题,因为我不希望任何非 0 线程拥有锁,一旦它们被解锁,我希望它们可以自由操作,直到它们完成列上的工作。
我试图通过将全局 "colReady" 变量设置为 0 来避免互斥锁。非零线程 while 循环直到 colReady = True。从逻辑上讲这是完全合理的,但它并没有以编程方式工作。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <pthread.h>
#define n 20
#define numThr 3
double **matrix;
int pivotReady[n] = { 0 };
pthread_cond_t cond_pivot_ready;
pthread_mutex_t cond_mutex;
int swapRows (int row1, int row2)
{
double *tempRow = matrix[row1];
matrix[row1] = matrix[row2];
matrix[row2] = tempRow;
return 0;
}
void randinit ()
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n + 1; j++) {
matrix[i][j] = drand48 ();
}
}
}
void rowReduce (void *arg);
void printMatrix ()
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n + 1; j++) {
printf (" %4.2f ", matrix[i][j]);
}
printf ("\n");
}
}
int main ()
{
pthread_cond_init (&cond_pivot_ready, NULL);
pthread_mutex_init (&cond_mutex, NULL);
int i, j;
double temp;
pthread_t p_threads[numThr];
pthread_attr_t attr;
pthread_attr_init (&attr);
//create matrix
matrix = malloc (sizeof (double *) * n);
for (i = 0; i < n; i++) {
*(matrix + i) = malloc (sizeof (double) * (n + 1));
}
randinit ();
for (i = 0; i < numThr; i++) {
pthread_create (&p_threads[i], &attr, rowReduce, (void *) ((long) i));
}
for (i = 0; i < numThr; i++) {
pthread_join (p_threads[i], NULL);
}
printf ("Final Matrix:\n");
printMatrix ();
return 0;
}
void rowReduce (void *arg)
{
int id = (int) arg;
int i, pivot, row;
double ratio, temp, max;
int maxRow;
for (pivot = 0; pivot < n - 1; pivot++) {
//PIVOT THREAD
if (id == 0) {
pthread_mutex_lock (&cond_mutex);
max = matrix[pivot][pivot]
maxRow = pivot;
for (i = pivot + 1; i < n; i++) {
temp = matrix[i][pivot];
if (temp > max) {
max = temp;
maxRow = i;
}
}
swapRows (pivot, maxRow);
pivotReady[pivot] = 1;
pthread_cond_signal (&cond_pivot_ready);
for (row = pivot + 1 + id; row < n; row += numThr) {
ratio = matrix[row][pivot] / matrix[pivot][pivot];
printf ("t1: row = %d, piv = %d, ratio = %f\n", row, pivot,
ratio);
for (int i = pivot; i < n + 1; i++) {
matrix[row][i] -= ratio * matrix[pivot][i];
}
}
pthread_mutex_unlock (&cond_mutex);
}
//NON-PIVOT THREAD
else {
pthread_mutex_lock (&cond_mutex);
while (!(pivotReady[pivot])) {
pthread_cond_wait (&cond_pivot_ready, &cond_mutex);
}
for (row = pivot + 1 + id; row < n; row += numThr) {
ratio = matrix[row][pivot] / matrix[pivot][pivot];
for (int i = pivot; i < n + 1; i++) {
matrix[row][i] -= ratio * matrix[pivot][i];
}
}
pthread_mutex_unlock (&cond_mutex);
}
}
//printf("rowReduce called with id = %d\n", id);
pthread_exit (0);
}
此程序应该打印一个已放入上三角形式的随机矩阵。
您只需要在访问 pivotReady[pivot]
时按住 cond_mutex
,因为这是它保护的唯一共享状态。
您还需要使用 pthread_cond_broadcast()
而不是 pthread_cond_signal()
,因为您需要 所有 等待线程在枢轴准备就绪后继续。
为了不重复行处理代码而进行了小幅重构后,它看起来像:
for (pivot = 0; pivot < n - 1; pivot++) {
//PIVOT THREAD
if (id == 0) {
max = matrix[pivot][pivot];
maxRow = pivot;
for (i = pivot + 1; i < n; i++) {
temp = matrix[i][pivot];
if (temp > max) {
max = temp;
maxRow = i;
}
}
swapRows (pivot, maxRow);
pthread_mutex_lock (&cond_mutex);
pivotReady[pivot] = 1;
pthread_cond_broadcast (&cond_pivot_ready);
pthread_mutex_unlock (&cond_mutex);
}
//NON-PIVOT THREAD
else {
pthread_mutex_lock (&cond_mutex);
while (!(pivotReady[pivot])) {
pthread_cond_wait (&cond_pivot_ready, &cond_mutex);
}
pthread_mutex_unlock (&cond_mutex);
}
for (row = pivot + 1 + id; row < n; row += numThr) {
ratio = matrix[row][pivot] / matrix[pivot][pivot];
for (int i = pivot; i < n + 1; i++) {
matrix[row][i] -= ratio * matrix[pivot][i];
}
}
}
如有必要,我可以 post 我的代码,但我的问题主要是概念性的。我正在使用线程实现高斯消去法。我有 p 个 pthreads 按列主要顺序在 nxn 矩阵上运行。在任何 p 线程开始对列进行操作之前,必须执行行操作以将该列中具有最大值的行向上移动到对角线上。所以我需要每个线程都等待,然后统一操作。目前,在每一列,每个线程都会检查它的 id,id=0 的线程将执行行操作。我的问题是如何让除 id=0 之外的所有线程等待,然后统一运行。
我试过使用互斥锁和条件。这些似乎不起作用,因为它们将所有访问权限授予单个线程。据我了解,只能通过让线程请求一个已经存在的锁来以这种方式阻塞线程,因此它必须等待。这对我来说是个问题,因为我不希望任何非 0 线程拥有锁,一旦它们被解锁,我希望它们可以自由操作,直到它们完成列上的工作。
我试图通过将全局 "colReady" 变量设置为 0 来避免互斥锁。非零线程 while 循环直到 colReady = True。从逻辑上讲这是完全合理的,但它并没有以编程方式工作。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <pthread.h>
#define n 20
#define numThr 3
double **matrix;
int pivotReady[n] = { 0 };
pthread_cond_t cond_pivot_ready;
pthread_mutex_t cond_mutex;
int swapRows (int row1, int row2)
{
double *tempRow = matrix[row1];
matrix[row1] = matrix[row2];
matrix[row2] = tempRow;
return 0;
}
void randinit ()
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n + 1; j++) {
matrix[i][j] = drand48 ();
}
}
}
void rowReduce (void *arg);
void printMatrix ()
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n + 1; j++) {
printf (" %4.2f ", matrix[i][j]);
}
printf ("\n");
}
}
int main ()
{
pthread_cond_init (&cond_pivot_ready, NULL);
pthread_mutex_init (&cond_mutex, NULL);
int i, j;
double temp;
pthread_t p_threads[numThr];
pthread_attr_t attr;
pthread_attr_init (&attr);
//create matrix
matrix = malloc (sizeof (double *) * n);
for (i = 0; i < n; i++) {
*(matrix + i) = malloc (sizeof (double) * (n + 1));
}
randinit ();
for (i = 0; i < numThr; i++) {
pthread_create (&p_threads[i], &attr, rowReduce, (void *) ((long) i));
}
for (i = 0; i < numThr; i++) {
pthread_join (p_threads[i], NULL);
}
printf ("Final Matrix:\n");
printMatrix ();
return 0;
}
void rowReduce (void *arg)
{
int id = (int) arg;
int i, pivot, row;
double ratio, temp, max;
int maxRow;
for (pivot = 0; pivot < n - 1; pivot++) {
//PIVOT THREAD
if (id == 0) {
pthread_mutex_lock (&cond_mutex);
max = matrix[pivot][pivot]
maxRow = pivot;
for (i = pivot + 1; i < n; i++) {
temp = matrix[i][pivot];
if (temp > max) {
max = temp;
maxRow = i;
}
}
swapRows (pivot, maxRow);
pivotReady[pivot] = 1;
pthread_cond_signal (&cond_pivot_ready);
for (row = pivot + 1 + id; row < n; row += numThr) {
ratio = matrix[row][pivot] / matrix[pivot][pivot];
printf ("t1: row = %d, piv = %d, ratio = %f\n", row, pivot,
ratio);
for (int i = pivot; i < n + 1; i++) {
matrix[row][i] -= ratio * matrix[pivot][i];
}
}
pthread_mutex_unlock (&cond_mutex);
}
//NON-PIVOT THREAD
else {
pthread_mutex_lock (&cond_mutex);
while (!(pivotReady[pivot])) {
pthread_cond_wait (&cond_pivot_ready, &cond_mutex);
}
for (row = pivot + 1 + id; row < n; row += numThr) {
ratio = matrix[row][pivot] / matrix[pivot][pivot];
for (int i = pivot; i < n + 1; i++) {
matrix[row][i] -= ratio * matrix[pivot][i];
}
}
pthread_mutex_unlock (&cond_mutex);
}
}
//printf("rowReduce called with id = %d\n", id);
pthread_exit (0);
}
此程序应该打印一个已放入上三角形式的随机矩阵。
您只需要在访问 pivotReady[pivot]
时按住 cond_mutex
,因为这是它保护的唯一共享状态。
您还需要使用 pthread_cond_broadcast()
而不是 pthread_cond_signal()
,因为您需要 所有 等待线程在枢轴准备就绪后继续。
为了不重复行处理代码而进行了小幅重构后,它看起来像:
for (pivot = 0; pivot < n - 1; pivot++) {
//PIVOT THREAD
if (id == 0) {
max = matrix[pivot][pivot];
maxRow = pivot;
for (i = pivot + 1; i < n; i++) {
temp = matrix[i][pivot];
if (temp > max) {
max = temp;
maxRow = i;
}
}
swapRows (pivot, maxRow);
pthread_mutex_lock (&cond_mutex);
pivotReady[pivot] = 1;
pthread_cond_broadcast (&cond_pivot_ready);
pthread_mutex_unlock (&cond_mutex);
}
//NON-PIVOT THREAD
else {
pthread_mutex_lock (&cond_mutex);
while (!(pivotReady[pivot])) {
pthread_cond_wait (&cond_pivot_ready, &cond_mutex);
}
pthread_mutex_unlock (&cond_mutex);
}
for (row = pivot + 1 + id; row < n; row += numThr) {
ratio = matrix[row][pivot] / matrix[pivot][pivot];
for (int i = pivot; i < n + 1; i++) {
matrix[row][i] -= ratio * matrix[pivot][i];
}
}
}