Многопотоковые вычисления: достоинства и недостатки
Для преобразования предыдущего примера в многопотоковую задачу, необходимо произвести маленькие изменения - функция, вычисляющая значение, должна работать отдельным потоком.
int SIZE_I = 4;
int SIZE_J = 4;
double X[SIZE_I][SIZE_J];
double S[SIZE_I][SIZE_J];
struct DATA_
{
double x;
int i;
int z;
}
typedef struct DATA_ DATA;
double f(double x)
{
//какие-то вычисления
}
void *thread_f(void *arg) //функция для вычисления элемента матрицы
{
DATA* a = (DATA*)arg; //преобразуем данные
X[a->i][a->z] = f([a->x]); //вычисляем
}
main_evalution()
{
pthread_t thread; //идентификатор потока
DATA *arg; //данные для передачи в поток
for (int i=0;i<SIZE_I; P ++i)<>
{
for (int z=0; z<SIZE_J; P ++z)<>
{
// создаем
arg = new DATA;
//инициализируем данные
arg->i = i; arg->z = z; arg->x = S[i][z];
//создаем поток
pthread_create(&thread, NULL, thread_f, (void *)arg);
//переводим в отсоединенное состояние
pthread_detach(thread);
}
}
}
В результате сделанных изменений, вычисление каждого элемента будет происходить в отдельном потоке. Недостатком такого метода является сложность - необходимо всегда учитывать то, что две нити могут обратиться к одним и тем же даным - одна для чтения, другая для записи, и в таком случае нельзя гарантировать достоверность данных. Т.е. необходимо устанавливать/проверять блокировки, обеспечивать синхронизацию выполнения и т.п. Достоинство - повышение производительности. Так в нашем примере, процесс не ждет выполнения всех нитей, т.е. он не ждет когда все елементы матрицы заполняться, а продолжает свою работу. В случае когда дальнейшая работа программы зависит от полученных вычислений, можно приостановить основной процесс до завершения всех нитей.