Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)
Paste
Pasted as C++ by dark ( 15 years ago )
// Matrix_Multiply.cpp: .
//
#include "pthread.h"
#include "stdio.h"
#include "iostream"
#include <stdlib.h>
#include <time.h>
int rand(int a, int b) // рандом в диапазоне от а до b
{
return rand()%(b - a - 1) + a;
}
pthread_mutex_t lock; // переменная мьютекс, для блокировки
int count_of_threads = 0; // глобальная переменная, используется для проверки завершения всех потоков.
//Класс, содержащий входные и результирующую матрицы
//
class unit
{
public:
int *res; // результирующая матрица
int *mat1; // первая матрица
int *mat2; // вторая матрица
int dim; // размерность матриц
unit( int dim_ ) //параметр конструктора - размерность матриц
{
dim = dim_;
mat1 = new int[dim * dim];
mat2 = new int[dim * dim];
res = new int[dim * dim];
}
void print(int *mat) //функция для вывода на экран матрицы. Служит для проверки правильности перемножения
{ //Если все элементы перемножаемых матриц инициализированы единицами, то все элементы результирующей матрицы будут равны размерности матриц
for(int i(0); i < dim; ++i)
{
for(int j(0); j < dim; ++j)
{
printf("%d ", mat[i * dim + j]);
}
printf("n");
}
}
void init( int value = 0 ) //метод для инициализации матриц, если value = 0, то матрицы инициализируются рандомно (mat1 равняется mat2, фактически идет перемножение матрицы на саму себя)
{ //если value = любому числу, матрицы инициализируются этим числом
int elem = value;
if(value != 0)
for(int i(0); i < dim * dim; ++i)
{
mat1[i] = elem;
mat2[i] = elem;
}
else
for(int i(0); i < dim * dim; ++i)
{
elem = rand(0, 10);
mat1[i] = elem;
mat2[i] = elem;
}
}
~unit()
{
delete []mat1;
delete []mat2;
delete []res;
}
};
unit *main_data; // глобальный указатель на данные
struct ind // структура, служащая для передачи параметров в поток.
{
int i; //указывает строку, с которой необходимо продолжить умножение
int part; //диапазон строк, которые задействованы в умножении
ind()
{ //
i = 0;
part = 0;
}
inline void set(int x)
{
i = x;
}
~ind(){};
};
void *Multiply( void *index) // функция, которую выполняют потоки.
// перемножение выполняется следующим способом, первая матрица разрезается на равные части по строкам в зависимости от количества потоков
// далее каждый поток умножает свой диапазон строк первой матрицы на вторую матрицу, в результате получается диапазон строк результирующей матрицы
/*
xxxxxx ****** xxxxxx
xxxxxx ****** xxxxxx
****** ****** ******
****** x ****** = ******
****** ****** ******
****** ****** ******
*/
{
ind *t = (ind *) index; // принимаем параметр
int i = t->i, // записываем номер строки, с которой поток начнет свои вычисления
part = t->part; // и записываем диапазон строк
int dim = main_data->dim, // получаем указатели на наши данные
*mat1 = main_data->mat1,
*mat2 = main_data->mat2,
*res_mat = main_data->res;
int i_border = i + part;
int res(0);
/*Multiply part of matrix*/
for(int ii(i) ; ii < i_border; ++ii)
{
for(int jj(0) ; jj < dim; ++jj)
{
for(int k(0); k < dim; ++k)
{
int m1 = ii * dim + k; //
int m2 = k * dim + jj; //
res += mat1[m1] * mat2[m2]; //
}
res_mat[ii * dim + jj] = res; // ccnt
res = 0;
}
}
pthread_mutex_lock(&lock;); // блокируем мьютекс
count_of_threads++; // при завершении потока, он увеличивает значение переменной count_of_threads
pthread_mutex_unlock(&lock;);// разблокируем мьютекс
pthread_exit(NULL); // завершаем работу потока
}
void *check( void * param ) // фукнция проверки завершения всех вычислительных потоков
{
int *num_threads = (int *) param; // в параметре получаем количество потоков
//printf("%dn", *num_threads);
while(1) // проверяем все ли потоки завершились
{
//printf("%dn", count_of_threads);
if( count_of_threads == *num_threads)
break;
}
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
int dim, num_threads;
pthread_mutex_init(&lock;, NULL);
std::cout << "Input dimention of matrix: ";
std::cin >> dim; //вводим размерность матриц
std::cout << "Input count of threads: ";
std::cin >> num_threads; //вводим количество вычислительных потоков
unit matrixs(dim); // создаем наши матрицы
matrixs.init(1); // инициализируем их
main_data = &matrixs;
if( dim % num_threads != 0) // проверка на то, чтобы матрица равномерно разрезалась на части
{
std::cout << "[WARNING!] nPlease input dimention of matrix and number of threads so, that its divided evenly!"<< std::endl;
return 1;
}
ind *index = new ind[ num_threads ]; // создаем параметры для передачи в потоки
pthread_t *threads = new pthread_t[ num_threads ]; // создаем идентификаторы для вычислительных потоков
std::cout << "[START] n Creating threads..."<< std::endl;
int part = dim / num_threads;
long rc;
int cnt(0);
std::cout << "[WAITING] n Threads is work..."<< std::endl;
clock_t t1;
t1 = clock(); // засекаем время
for ( int i(0); i < main_data->dim; i += part )
{
index[ cnt ].part = part; //
index[ cnt ].set( i );
rc = pthread_create(&threads;[ cnt ], NULL, Multiply, &index;[ cnt ]); // запускаем вычислительные потоки
if (rc)
{
printf("[ ERROR ] return code from pthread_create() is %dn", rc);
exit(-1);
}
pthread_detach(threads[ cnt ]); // отсоединяем поток
cnt++;
}
pthread_t check_thread; // идентификатор для проверочного потока
pthread_create(✓_thread, NULL, check, #_threads); // создаем поток, который следит за выполнением других потоков
rc = pthread_join(check_thread, NULL); // ожидаем завершения потока check
t1 = clock() - t1; // замеряем время выполнения потоков
// вывод на экран результатов
std::cout << "[RESULT] n Time = " << t1 << ";" << std::endl;
// записываем данные в файл
FILE *out = fopen("1.csv","a+");
if (out == NULL)
printf ("Can not create or open filen");
else
{
fprintf(out,"%d;",count_of_threads);
fprintf(out,"%dn",t1);
}
fclose(out);
pthread_mutex_destroy(&lock;);
//main_data->print(main_data->res); // если раскомментить, то на экран будет выводиться результирующая матрица
system(" oocalc 1.csv"); // запуск файла со статистикой в OpenOffice Calc.
return 0;
}
Revise this Paste