Project
Loading...
Searching...
No Matches
SymMatrixSolver.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#include "SymMatrixSolver.h"
18#include "GPUCommonLogger.h"
19
20#include <iostream>
21#include <random>
22#include <iomanip>
23#include <chrono>
24
25using namespace std;
26using namespace o2::gpu;
27
29
31{
32 // Upper Triangulization
33 for (int32_t i = 0; i < mN; i++) {
34 double* rowI = &mA[i * mShift];
35 double* rowIb = &mA[i * mShift + mN];
36 double c = (fabs(rowI[i]) > 1.e-10) ? 1. / rowI[i] : 0.;
37 double* rowJ = rowI + mShift;
38 for (int32_t j = i + 1; j < mN; j++, rowJ += mShift) { // row j
39 if (rowI[j] != 0.) {
40 double aij = c * rowI[j]; // A[i][j] / A[i][i]
41 for (int32_t k = j; k < mShift; k++) {
42 rowJ[k] -= aij * rowI[k]; // A[j][k] -= A[i][k]/A[i][i]*A[j][i]
43 }
44 rowI[j] = aij; // A[i][j] /= A[i][i]
45 }
46 }
47 for (int32_t k = 0; k < mM; k++) {
48 rowIb[k] *= c;
49 }
50 }
51 // Diagonalization
52 for (int32_t i = mN - 1; i >= 0; i--) {
53 double* rowIb = &mA[i * mShift + mN];
54 double* rowJb = rowIb - mShift;
55 for (int32_t j = i - 1; j >= 0; j--, rowJb -= mShift) { // row j
56 double aji = mA[j * mShift + i];
57 if (aji != 0.) {
58 for (int32_t k = 0; k < mM; k++) {
59 rowJb[k] -= aji * rowIb[k];
60 }
61 }
62 }
63 }
64}
65
67{
68 for (int32_t i = 0; i < mN; i++) {
69 LOG(info) << "";
70 for (int32_t j = 0; j < mN; j++) {
71 LOG(info) << std::fixed << std::setw(5) << std::setprecision(2) << A(i, j) << " ";
72 }
73 LOG(info) << " | ";
74 for (int32_t j = 0; j < mM; j++) {
75 LOG(info) << std::fixed << std::setw(5) << std::setprecision(2) << B(i, j) << " ";
76 }
77 }
78 LOG(info) << std::setprecision(-1);
79}
80
81int32_t SymMatrixSolver::test(bool prn)
82{
83 constexpr int32_t n = 30;
84 constexpr int32_t d = 3;
85
86 // std::random_device rd; // Will be used to obtain a seed for the random
87 std::mt19937 gen(1); // Standard mersenne_twister_engine seeded with 1
88 std::uniform_real_distribution<> uniform(-.999, .999);
89
90 double maxDiff = 0.;
91 int32_t nTries = 10000;
92
93 auto tmpTime = std::chrono::high_resolution_clock::now();
94 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(tmpTime - tmpTime);
95 auto durationMult = duration;
96
97 for (int32_t iter = 0; iter < nTries; iter++) {
98
99 double x[n][d];
100 double A[n][n];
101 {
102 for (int32_t i = 0; i < n; i++) {
103 for (int32_t j = 0; j < d; j++) {
104 x[i][j] = 1. * uniform(gen);
105 }
106 }
107 for (int32_t i = 0; i < n; i++) {
108 A[i][i] = fabs(2. + uniform(gen));
109 }
110 for (int32_t i = 0; i < n; i++) {
111 for (int32_t j = i + 1; j < n; j++) {
112 A[i][j] = A[i][i] * A[j][j] * uniform(gen);
113 A[j][i] = A[i][j];
114 }
115 }
116 for (int32_t i = 0; i < n; i++) {
117 A[i][i] = A[i][i] * A[i][i];
118 }
119 if (prn && iter == nTries - 1) {
120 for (int32_t i = 0; i < n; i++) {
121 LOG(info) << "";
122 for (int32_t j = 0; j < n; j++) {
123 LOG(info) << std::fixed << std::setw(5) << std::setprecision(2) << A[i][j] << " ";
124 }
125 }
126 LOG(info) << "";
127 }
128 }
129 double b[n][d];
130 auto startMult = std::chrono::high_resolution_clock::now();
131 for (int32_t i = 0; i < n; i++) {
132 for (int32_t k = 0; k < d; k++) {
133 b[i][k] = 0.;
134 }
135 for (int32_t j = 0; j < n; j++) {
136 for (int32_t k = 0; k < d; k++) {
137 b[i][k] += x[j][k] * A[i][j];
138 }
139 }
140 }
141 auto stopMult = std::chrono::high_resolution_clock::now();
142 durationMult += std::chrono::duration_cast<std::chrono::nanoseconds>(stopMult - startMult);
143
144 SymMatrixSolver sym(n, d);
145
146 for (int32_t i = 0; i < n; i++) {
147 for (int32_t k = 0; k < d; k++) {
148 sym.B(i, k) = b[i][k];
149 }
150 for (int32_t j = i; j < n; j++) {
151 sym.A(i, j) = A[i][j];
152 }
153 }
154
155 auto start = std::chrono::high_resolution_clock::now();
156 sym.solve();
157 auto stop = std::chrono::high_resolution_clock::now();
158 duration += std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
159
160 double diff = 0.;
161 for (int32_t i = 0; i < n; i++) {
162 for (int32_t k = 0; k < d; k++) {
163 double t = fabs(x[i][k] - sym.B(i, k));
164 if (diff < t) {
165 diff = t;
166 }
167 }
168 }
169 if (maxDiff < diff) {
170 maxDiff = diff;
171 }
172 // LOG(info) << std::defaultfloat ;
173 // LOG(info) << "\n\n max diff " <<diff << "\n";
174 }
175
176 int32_t ok = (maxDiff < 1.e-7);
177
178 if (prn || !ok) {
179 LOG(info) << std::defaultfloat;
180 LOG(info) << "\n\n Overall max diff " << maxDiff << "\n";
181 LOG(info) << " time " << duration.count() / nTries;
182 LOG(info) << " time multiplication " << durationMult.count() / nTries;
183 }
184 return ok;
185}
default_random_engine gen(dev())
int32_t i
ClassImp(o2::gpu::SymMatrixSolver)
Definition of SymMatrixSolver class.
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Definition A.h:16
Definition B.h:16
double & B(int32_t i, int32_t j)
access to B elements
double & A(int32_t i, int32_t j)
access to A elements
static int32_t test(bool prn=0)
Test the class functionality. Returns 1 when ok, 0 when not ok.
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint start
Definition glcorearb.h:469
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"