Skip to content

Commit 15d3417

Browse files
authoredAug 9, 2022
Perfomance: Matrix opti & new tests (EnjoMitch#43)
1 parent dcdd951 commit 15d3417

File tree

6 files changed

+152
-18
lines changed

6 files changed

+152
-18
lines changed
 

‎lib/Statistical/Distrib.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@ Distrib::~Distrib()
2626
DistribData Distrib::GetDistrib(const EnjoLib::VecD & data, int numBins) const
2727
{
2828
DistribData distrib;
29-
EnjoLib::VecD dataSorted = data;
30-
AlgoSTDIVec<FP>().Sort(&dataSorted);
31-
std::vector<Pair<FP, FP>> distribData;
32-
if (dataSorted.size() < 2)
29+
const size_t dsz = data.size();
30+
if (dsz < 2)
3331
{
3432
return distrib;
3533
}
34+
EnjoLib::VecD dataSorted = data;
35+
AlgoSTDIVec<FP>().Sort(&dataSorted);
36+
std::vector<Pair<FP, FP>> distribData;
37+
distribData.reserve(numBins);
38+
3639
const FP lo = dataSorted.First();
3740
const FP hi = dataSorted.Last();
3841
const FP rangeDiff = hi - lo;
@@ -46,7 +49,7 @@ DistribData Distrib::GetDistrib(const EnjoLib::VecD & data, int numBins) const
4649
const FP valMax = lo + binLen * (i);
4750
const FP valMid = (valMax + valMin) / 2.0;
4851
int numOcurrences = 0;
49-
for (const FP val : dataSorted)
52+
for (const FP & val : dataSorted)
5053
{
5154
if (valMin <= val && val <= valMax)
5255
{

‎lib/Statistical/Matrix.cpp

+52-5
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,22 @@ Matrix::Matrix()
6161
Matrix::Matrix(int n)
6262
: m_impl(new Impl())
6363
{
64+
const VecD def(n);
6465
this->reserve(n);
6566
for (int i = 0; i < n; ++i)
66-
push_back( VecD(n) );
67+
//push_back( VecD(n) );
68+
push_back( def );
6769
}
6870

6971
Matrix::Matrix(int n, int m)
7072
: m_impl(new Impl())
7173
{
74+
const VecD def(m);
7275
this->reserve(n);
7376
for (int i = 0; i < n; ++i)
74-
push_back( VecD(m) );
77+
//push_back( VecD(m) );
78+
push_back( def );
79+
//m_impl->dat.emplace_back( std::move(VecD(m)) );
7580
}
7681

7782
Matrix::Matrix(const STDFWD::vector<VecD> & vec)
@@ -167,9 +172,25 @@ Matrix Matrix::T() const
167172
const int nrows = GetNRows();
168173
const int ncols = GetNCols();
169174
Matrix t(ncols, nrows);
175+
176+
int i = 0;
177+
for (const VecD & row : *this)
178+
{
179+
int j = 0;
180+
for (const FP & val : row)
181+
//for (VecD & tRow : t) // Not substantially faster
182+
{
183+
t[j++][i] = val;
184+
//tRow[i] = row[j++];
185+
}
186+
++i;
187+
}
188+
189+
/*
170190
for ( int i = 0; i < nrows; ++i )
171191
for ( int j = 0; j < ncols; ++j )
172-
t[j][i] = at(i)[j];
192+
t[j][i] = operator[](i)[j];
193+
*/
173194
return t;
174195
}
175196

@@ -186,7 +207,7 @@ Matrix Matrix::FilterByMaskD(const EnjoLib::VecD & mask) const
186207
row.reserve(maskSize);
187208
for (size_t j = 0; j < maskSize; ++j)
188209
{
189-
const double weight = mask.at(j);
210+
const FP weight = mask.at(j);
190211
row.push_back(at(i).at(j) * weight);
191212
//row.push_back(this->operator[](i)[j]);
192213
}
@@ -255,17 +276,43 @@ Matrix Matrix::operator * (const Matrix & par) const
255276
const int nrows = prod.GetNRows();
256277
const int ncols = prod.GetNCols();
257278
const int ncolsThis = GetNCols();
279+
int i = 0;
280+
for (VecD & row : prod)
281+
{
282+
const VecD & thisI = this->operator[](i);
283+
int j = 0;
284+
for (FP & valProd : row)
285+
{
286+
FP prodSum = 0;
287+
288+
//for (int ai = 0; ai < ncolsThis; ++ai )
289+
int ai = 0;
290+
for (const VecD & vecAI : par)
291+
//for (const FP & valThisAI : thisI) // Slower
292+
{
293+
//prodSum += at(i).at(ai) * par.at(ai).at(j);
294+
//prodSum += thisI[ai] * par[ai][j];
295+
prodSum += thisI[ai++] * vecAI[j];
296+
//prodSum += valThisAI * par[ai++][j];
297+
}
298+
valProd = prodSum;
299+
++j;
300+
}
301+
++i;
302+
}
303+
/*
258304
for (int i = 0; i < nrows; ++i)
259305
for (int j = 0; j < ncols; ++j)
260306
{
261-
double prodSum = 0;
307+
FP prodSum = 0;
262308
for (int ai = 0; ai < ncolsThis; ++ai )
263309
{
264310
//prodSum += at(i).at(ai) * par.at(ai).at(j);
265311
prodSum += this->operator[](i)[ai] * par[ai][j];
266312
}
267313
prod[i][j] = prodSum;
268314
}
315+
*/
269316
return prod;
270317
}
271318

‎lib/Statistical/Statistical.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,12 @@ VecD Statistical::MeanCols( const Matrix & m ) const
407407
{
408408
VecD ret;
409409
const Matrix & t = m.T();
410-
for (size_t i = 0; i < t.size(); ++i)
410+
//const size_t tsz = t.size();
411+
//for (size_t i = 0; i < tsz; ++i)
412+
for (const VecD & row : t)
411413
{
412-
ret.push_back(t.at(i).Mean());
414+
//ret.push_back(t.at(i).Mean());
415+
ret.push_back(row.Mean());
413416
}
414417
return ret;
415418
}

‎tests/EnjoLibPerfTest/src/PcaTest.cpp

+82-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "PcaTest.h"
22

33
//#include <Util/ProgressMonitHigh.hpp>
4+
#include <Ios/Osstream.hpp>
5+
#include <Ios/Ofstream.hpp>
46
#include <Util/CoutBuf.hpp>
57
#include <Util/VecD.hpp>
68
#include <Util/Timer.hpp>
@@ -20,26 +22,43 @@ PcaTest::PcaTest()
2022
{
2123
const Timer timer;
2224
LOGL << "Running performance tests" << Nl;
25+
TestMatrixTransp();
26+
TestMatrixMul();
2327
TestDistrib();
28+
//return;
2429
TestPca1();
30+
TestPcaAuto();
31+
32+
2533
Log("Total", timer, 0);
2634
}
2735

2836
PcaTest::~PcaTest(){}
2937

3038
void PcaTest::Log(const EnjoLib::Str & descr, const EnjoLib::Timer & timer, const int iter) const
3139
{
32-
LOGL << descr <<"\t (" << iter << " iters)\t" << " finished in: " << timer.GetElapsedSeconds() << " s\n";
40+
#ifdef EL_FLOATING_POINT_LOW_PRECISION
41+
const Str fpName = "float";
42+
#else
43+
const Str fpName = "double";
44+
#endif // EL_FLOATING_POINT_LOW_PRECISION
45+
Osstream oss;
46+
oss << descr <<"\t (" << iter << " iters)\t" << " finished in: " << timer.GetElapsedSeconds() << " s\n";
47+
const Str fname = "perf-test-" + fpName + ".log";
48+
Ofstream ofs(fname, true, true);
49+
ofs << oss.str();
50+
LOGL << oss.str();
51+
//{LOGL << "Saved log to " << fname << Nl;}
3352
}
3453

3554
void PcaTest::TestDistrib() const
3655
{
37-
const int ITER = 4e3;
38-
const Timer timer;
56+
const int ITER = 3e3;
3957
const RandomMath rmath;
4058
const Distrib distr;
4159

4260
VecD data;
61+
const Timer timer;
4362
for (int i = 0; i < ITER; ++i)
4463
{
4564
// break;
@@ -54,16 +73,32 @@ void PcaTest::TestDistrib() const
5473
const DistribData & distData = distr.GetDistrib(data, 50);
5574
}
5675

57-
Log("Distrib", timer, ITER);
76+
Log("Distrib\t", timer, ITER);
5877
}
5978

6079
void PcaTest::TestPca1() const
6180
{
62-
const int ITER = 6e3;
81+
const int ITER = 1e4;
82+
const int numFeaturesToLeave = 3;
83+
const Matrix & iris = DataSets::GetIris();
84+
const auto eig = EigenFactory().Create(EIGENTYPE_DEFAULT);
6385
const Timer timer;
86+
for (int i = 0; i < ITER; ++i)
87+
{
88+
const PCA pca(*eig, iris, numFeaturesToLeave);
89+
const Matrix & xtr = pca.Transform(iris);
90+
const Matrix & xinv = pca.InverseTransform(xtr);
91+
}
92+
Log("PCA_1\t", timer, ITER);
93+
}
94+
95+
void PcaTest::TestPcaAuto() const
96+
{
97+
const int ITER = 4e3;
6498
const Matrix & data = DataSets::GetIris();
6599
const auto eig = EigenFactory().Create(EIGENTYPE_DEFAULT);
66100
const PCAAuto pcaAuto;
101+
const Timer timer;
67102

68103
for (int i = 0; i < ITER; ++i)
69104
{
@@ -73,5 +108,46 @@ void PcaTest::TestPca1() const
73108
const int minComp1 = pcaAuto.FindMinimalComponents(*eig, data, quality);
74109
const int minComp2 = pcaAuto.FindMinimalComponentsBinSearch(*eig, data, quality);
75110
}
76-
Log("PCA1", timer, ITER);
111+
Log("PCA_auto", timer, ITER);
112+
}
113+
114+
void PcaTest::TestMatrixMul() const
115+
{
116+
Matrix matData;
117+
matData.push_back({1, 2, 3});
118+
matData.push_back({1, 2, 3});
119+
matData.push_back({1, 2, 3});
120+
matData.push_back({1, 2, 3});
121+
matData.push_back({1, 2, 3});
122+
matData.push_back({1, 2, 3});
123+
matData.push_back({1, 2, 3});
124+
125+
const Matrix & matDataT = matData.T();
126+
const Timer timer;
127+
const int ITER = 2e5;
128+
for (int i = 0; i < ITER; ++i)
129+
{
130+
const Matrix & matMul = matDataT * matData;
131+
}
132+
Log("Matrix mul", timer, ITER);
133+
}
134+
135+
void PcaTest::TestMatrixTransp() const
136+
{
137+
Matrix matData;
138+
matData.push_back({1, 2, 3});
139+
matData.push_back({1, 2, 3});
140+
matData.push_back({1, 2, 3});
141+
matData.push_back({1, 2, 3});
142+
matData.push_back({1, 2, 3});
143+
matData.push_back({1, 2, 3});
144+
matData.push_back({1, 2, 3});
145+
146+
const Timer timer;
147+
const int ITER = 4e5;
148+
for (int i = 0; i < ITER; ++i)
149+
{
150+
const Matrix & matT = matData.T();
151+
}
152+
Log("Matrix Trans", timer, ITER);
77153
}

‎tests/EnjoLibPerfTest/src/PcaTest.h

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class PcaTest
1414

1515
void TestDistrib() const;
1616
void TestPca1() const;
17+
void TestPcaAuto() const;
18+
void TestMatrixMul() const;
19+
void TestMatrixTransp() const;
1720

1821
protected:
1922

‎util/ci-clang.sh

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/bin/bash
22

3+
OPTS=$1
34
MAKE=make
45
GEN="CodeBlocks - Unix Makefiles"
56
BUILD_DIR="build/clang"
@@ -11,6 +12,7 @@ CMAKE_CXX_COMPILER="${GCC_PREFIX}++"
1112
mkdir -p $BUILD_DIR && cd $BUILD_DIR
1213

1314
cmake -G "${GEN}" ../.. \
15+
${OPTS} \
1416
-DCMAKE_C_COMPILER="${CMAKE_C_COMPILER}" \
1517
-DCMAKE_CXX_COMPILER="${CMAKE_CXX_COMPILER}" \
1618
-DUSE_STATIC="ON" \

0 commit comments

Comments
 (0)
Please sign in to comment.