Welcome, guest! Login / Register - Why register?
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&#40;"1.csv","a+"&#41;;
  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&#40;" oocalc 1.csv"&#41;; // запуск файла со статистикой в OpenOffice Calc.
  return 0;
}

 

Revise this Paste

Your Name: Code Language: