Я реализовал добавление двух общих матриц, используя многопоточность и последовательный алгоритм.Я протестировал свою программу с двумя большими матрицами (2000x2000), которые содержали действительные числа (двойные числа), и результаты были очень хорошими.Операцию удалось закончить очень быстро.Позже я реализовал класс, представляющий комплексное число, и попытался повторить один и тот же сценарий с двумя матрицами, и обнаружил, что требуются целые годы, чтобы завершить весь процесс даже для двух матриц 50x50.Что я должен сделать, чтобы увеличить продолжительность выполнения?
Это метод, который создает потоки (прежде всего я создаю два одномерных массива, чтобы было легче обеспечить каждый поток своей начальной и конечной точкой):
template<typename T, typename Func>
Matrix<T> *calculateLinearDistribution(Matrix<T> *matrix1,
Matrix<T> *matrix2,
Func operation,
int nThreads) {
const int n = matrix1->getN(), m = matrix2->getM(), totalNumbers = n * m;
Matrix<T> *result = new Matrix<T>(n, m);
T *matrix1Unidim = new T[totalNumbers];
T *matrix2Unidim = new T[totalNumbers];
convertMatrixToUnidimensionalArray(matrix1, matrix1Unidim);
convertMatrixToUnidimensionalArray(matrix1, matrix2Unidim);
if (totalNumbers < nThreads) {
nThreads = totalNumbers;
}
const int quantityPerThread = totalNumbers / nThreads;
int rest = totalNumbers % nThreads;
int start = 0, end = 0;
std::vector<std::thread> threads;
std::chrono::milliseconds startTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
for (int i = 0; i < nThreads; i++) {
end += quantityPerThread;
if (rest > 0) {
end++;
rest--;
}
threads.push_back(std::thread(MultithreadedMethods<T, Func>::linearElementsDistribution, &matrix1Unidim[0],
&matrix2Unidim[0], result, start, end, operation));
start = end;
}
for (int i = 0; i < nThreads; i++) {
threads[i].join();
}
std::chrono::milliseconds endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
std::ofstream out(linearElemensStatisticsFile, std::ios_base::app);
std::chrono::milliseconds time = endTime - startTime;
out << "Dimensiune matrice: " << matrix1->getN() << "x" << matrix1->getM()
<< " | Nr. threads: " << nThreads << " | Timp de executie: " << time.count() << std::endl;
out.close();
delete[] matrix1Unidim;
delete[] matrix2Unidim;
return result;
}
Это функция, предоставленная потоку:
template<typename T, typename Func>
void MultithreadedMethods<T, Func>::linearElementsDistribution(T *matrix1,
T *matrix2,
Matrix<T> *result,
int start,
int end,
Func operation) {
const int m = result->getM();
for (int i = start; i < end; i++) {
result->getElements()[i / m][i % m] = operation(matrix1[i], matrix2[i]);
}
}
Здесь я запускаю процесс с действительными числами (это очень быстро):
Matrix<double> *linearDistributionResult = calculateLinearDistribution(matrix1,
matrix2,
[](double a, double b) {
return a +
b;
}, nThreads);
И, наконец, это плохая часть, где я пытаюсь использовать комплексные числа, и это занимает много времени и даже дает сбой по сравнению с последовательным результатом ...
Matrix<ComplexNumber> *linearDistributionResult = calculateLinearDistribution(matrix1,
matrix2,
[](ComplexNumber a,
ComplexNumber b) {
return ComplexNumber(
a.getRealComponent() +
b.getRealComponent(),
a.getImaginaryComponent() +
b.getImaginaryComponent());
}, nThreads);
Конечно, этоявляется последовательной реализацией (я хотел бы отметить, что это также очень медленно, когда я использую комплексные числа по сравнению с действительными числами):
template<typename T, typename Func>
Matrix<T> *calculateSequentialResult(Matrix<T> *matrix1,
Matrix<T> *matrix2,
Func operation) {
const int n = matrix1->getN(), m = matrix1->getM();
Matrix<T> *result = new Matrix<T>(n, m);
std::chrono::milliseconds startTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
result->getElements()[i][j] = operation(matrix1->getElements()[i][j], matrix2->getElements()[i][j]);
}
}
std::chrono::milliseconds endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
std::ofstream out(sequentialElementsStatistics, std::ios_base::app);
std::chrono::milliseconds time = endTime - startTime;
out << "Dimensiune matrice: " << matrix1->getN() << "x" << matrix1->getM()
<< " | Nr. threads: 1 | Timp de executie: " << time.count() << std::endl;
out.close();
return result;
}
ОБНОВЛЕНИЕ Это результат при использовании Very Sleepy Для анализа выполнения: 
Класс ComplexNumber:
class ComplexNumber {
private:
double realComponent;
double imaginaryComponent;
public:
ComplexNumber() {}
ComplexNumber(const ComplexNumber &complexNumber);
double getRealComponent() const;
ComplexNumber(double realComponent, double imaginaryComponent);
void setRealComponent(double realComponent);
double getImaginaryComponent() const;
void setImaginaryComponent(double imaginaryComponent);
friend std::ostream &operator<<(std::ostream &os, const ComplexNumber &complexNumber);
};
and the definition:
double ComplexNumber::getRealComponent() const {
return realComponent;
}
void ComplexNumber::setRealComponent(double realComponent) {
ComplexNumber::realComponent = realComponent;
}
double ComplexNumber::getImaginaryComponent() const {
return imaginaryComponent;
}
void ComplexNumber::setImaginaryComponent(double imaginaryComponent) {
ComplexNumber::imaginaryComponent = imaginaryComponent;
}
ComplexNumber::ComplexNumber(double realComponent, double imaginaryComponent) : realComponent(realComponent),
imaginaryComponent(imaginaryComponent) {
}
ComplexNumber::ComplexNumber(const ComplexNumber &complexNumber) {
this->imaginaryComponent = complexNumber.imaginaryComponent;
this->realComponent = complexNumber.realComponent;
}
std::ostream &operator<<(std::ostream &os, const ComplexNumber &complexNumber) {
if (complexNumber.imaginaryComponent == 0) {
os << std::to_string(complexNumber.realComponent);
} else if (complexNumber.realComponent == 0) {
os << std::to_string(complexNumber.imaginaryComponent) + "i";
} else
os << std::to_string(complexNumber.realComponent) + ((complexNumber.imaginaryComponent < 0) ?
("-" + std::to_string(complexNumber.imaginaryComponent) +
"i") :
("+" + std::to_string(complexNumber.imaginaryComponent) +
"i"));
return os;
}
Решено
Проблема заключалась в том, что я использовал регулярное выражение для анализа комплексного числас из файла, и они были очень медленными.После их замены мне удалось получить правильное поведение.