Матрица (которая учитывается при измерении) делает больше, чем амортизирует. Это не удивительно, потому что в умножении гораздо больше обращений к чтению (которые теперь получают доступ к последовательным байтам) по сравнению с дополнительными усилиями по созданию / записи транспонированной матрицы один раз.
исал код, который случайным образом генерирует две матрицы размером от 2х2 до 50х50. Затем я записываю время, которое требуется для каждого умножения матриц от измерений 2 до 50. Я записываю это время 100 раз, чтобы получить хорошее среднее значение для каждого случая 2 -50. Сначала программа запускается путем умножения матриц последовательно и записывает среднее время выполнения в CSV-файл. Затем он переходит к параллельному умножению матриц с использованием pthreads и записывает среднее время выполнения в отдельном файле CSV. Моя проблема в том, что среднее время выполнения для последовательного умножения намного короче, чем параллельное выполнение. Для матрицы размера 50 последовательное умножение занимает 500 микросекунд, а параллельное умножение - 2500 микросекунд. Это проблема из-за того, как я синхронизирую код? Или моя реализация потоков работает не очень хорошо и фактически заставляет код выполняться дольше? Я запускаю таймер после генерации матриц и останавливаю его после объединения всех потоков. Код потока изначально был написан для двух матриц неравномерного размера, поэтому он реализует алгоритм балансировки нагрузки.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <stdlib.h>
#include <pthread.h>
#include <cstdlib>
#include <ctime>
#include <sys/time.h>
#include <chrono>
#include <unistd.h>
using namespace std;
int n,i,j,t,k,l,MAX;
float randomnum,sum1, avg;
float matA[100][100];
float matB[100][100];
float matC[100][100];
struct Loading
{
int r;
int c;
int n;
int m;
};
// threads
pthread_t threads[100] = { 0 };
// indexes
int indexes[100] = {0};
// load balancing
Loading loads[100] = { 0 };
// for printing in thread
pthread_mutex_t M;
// run thread
void* multi(void* arg)
{
int index = *((int*)(arg));
Loading load = loads[index];
int i = 0;
int j = 0;
int k = 0;
int istart = load.r;
int jstart = load.c;
pthread_mutex_lock(&M);
// cout << "thread #" << index << " pid: " << getpid() << " starting " << " row " << istart << " col " << jstart << endl;
pthread_mutex_unlock(&M);
// logic to balance loads amongst threads using for loop
int n = load.n;
for (i = istart; i < MAX; i++)
{
for (j =jstart;n > 0 && j < MAX; j++,n--)
{
for (k = 0; k < MAX; k++)
{
matC[i][j] += matA[i][k] * matB[k][j];
}
pthread_mutex_lock(&M);
//cout << "row " << i << " col "<< j << " value " << matC[i][j] << endl;
pthread_mutex_unlock(&M);
}
jstart = 0;
if (n == 0)
{
pthread_mutex_lock(&M);
// cout << "thread #" << index << " pid: " << getpid() << " has completed " << endl;
pthread_mutex_unlock(&M);
return 0;
}
}
return 0;
}
int num_threads = 0;
int MAX_THREADS= 0;
int main()
{
pthread_mutex_init(&M, NULL);
srand ( time(NULL) );
//for (n=2; n<4; n++) {
ofstream myfile;
// myfile.open ("/home/gage/Desktop/timing/seqrecord.csv");
myfile.open ("seqrecord.csv");
myfile << "testtowork\n";
for (n=2; n<50; n++){
MAX =n;
myfile << n <<",";
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
matA[i][j] = ((float(rand()) / float(RAND_MAX)) * (100 - -50)) + -50;
matB[i][j] = ((float(rand()) / float(RAND_MAX)) * (100 - -50)) + -50;
}
}
for(t=0; t<101; t++){
//clock_t startTime = clock();
auto start = chrono::steady_clock::now();
for (i = 0; i < MAX; ++i)
for (j = 0; j < MAX; ++j)
for (k = 0; k < MAX; ++k)
{
matC[i][j] += matA[i][k] * matB[k][j];
}
//int stop_s=clock();
auto end = chrono::steady_clock::now();
//cout << double( clock() - startTime ) / (double)CLOCKS_PER_SEC/1000000000<< " milli-seconds." << endl;
//cout << chrono::duration_cast<chrono::microseconds>(end - start).count() <<endl;
myfile << chrono::duration_cast<chrono::microseconds>(end - start).count() <<",";
sum1 = sum1+chrono::duration_cast<chrono::microseconds>(end - start).count();
}
avg = sum1 / 100;
myfile << "Average execution" << "," << avg << "\n";
sum1 =0;
avg = 0;
// }
}
myfile.close();
ofstream myfile1;
myfile1.open ("parallel.csv");
myfile1 << "testtowork\n";
for (n=2; n<51; n++)
{
MAX = n;
MAX_THREADS = n*n;
num_threads =n;
myfile1 << n <<",";
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
matA[i][j] = ((float(rand()) / float(RAND_MAX)) * (100 - -50)) + -50;
matB[i][j] = ((float(rand()) / float(RAND_MAX)) * (100 - -50)) + -50;
}
}
for(t=0; t<101; t++){
//clock_t startTime = clock();
auto start = chrono::steady_clock::now();
/,/ calculade load balancing
// cout << "calculation load balancing" << endl;
double nwhole = (double)MAX_THREADS / num_threads;
double last = 0;
double sum = 0;
int k = 0;
loads[k].r = 0;
loads[k].c = 0;
loads[k].n = 0;
while (k < num_threads)
{
sum = sum + nwhole;
loads[k].n = (int)sum - (int)last;
// check last length
if(k == num_threads-1 && sum != MAX_THREADS)
{
sum=MAX_THREADS;
loads[k].n=(int)sum - (int)last;
}
// display result
// cout << (int)last << " to " << (int)sum << " length: " << (int)sum - int(last) << endl;
k++;
if(k < num_threads)
{
loads[k].r = ((int)sum) / MAX;
loads[k].c = ((int)sum) % MAX;
}
last = sum;
}
//cout << "making threads" << endl;
void* exit_status;
int rc;
for( i = 0; i < num_threads ; i++ ) {
// cout << "main() : creating thread, " << i << endl;
indexes[i] = i;
rc = pthread_create(&threads[i], NULL, multi, (void *)&indexes[i]);
if (rc) {
// cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
// wait for threads to end
for (j = 0; j < num_threads; j++)
{
pthread_join(threads[j], &exit_status);
}
auto end = chrono::steady_clock::now();
//cout << double( clock() - startTime ) / (double)CLOCKS_PER_SEC/1000000000<< " milli-seconds." << endl;
//cout << chrono::duration_cast<chrono::microseconds>(end - start).count() <<endl;
myfile1 << chrono::duration_cast<chrono::microseconds>(end - start).count() <<",";
sum1 = sum1+chrono::duration_cast<chrono::microseconds>(end - start).count();
}
avg = sum1 / 100;
myfile1 << "Average" << "," << avg << "\n";
sum1 =0;
avg = 0;
}
return 0;
}