Skip to content

Commit a7fa732

Browse files
committed
[ML] Convert std::shared_ptrs to std::unique_ptrs where possible
1 parent c6f3be3 commit a7fa732

File tree

80 files changed

+883
-609
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+883
-609
lines changed

docs/CHANGELOG.asciidoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ Secure the ML processes by preventing system calls such as fork and exec. The Li
4141
Seccomp BPF to intercept system calls and is available in kernels since 3.5. On Windows Job Objects prevent
4242
new processes being created and macOS uses the sandbox functionality ({pull}98[#98])
4343

44+
Fix a bug causing us to under estimate the memory used by shared pointers and reduce the memory consumed
45+
by unnecessary reference counting ({pull}108[#108])
46+
4447
=== Bug Fixes
4548

4649
Age seasonal components in proportion to the fraction of values with which they're updated ({pull}88[#88])

include/api/CForecastRunner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class API_EXPORT CForecastRunner final : private core::CNonCopyable {
115115
using TForecastModelWrapper = model::CForecastDataSink::SForecastModelWrapper;
116116
using TForecastResultSeries = model::CForecastDataSink::SForecastResultSeries;
117117
using TForecastResultSeriesVec = std::vector<TForecastResultSeries>;
118-
using TMathsModelPtr = std::shared_ptr<maths::CModel>;
118+
using TMathsModelPtr = std::unique_ptr<maths::CModel>;
119119

120120
using TStrUSet = boost::unordered_set<std::string>;
121121

include/core/CMemory.h

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -287,21 +287,25 @@ class CORE_EXPORT CMemory : private CNonInstantiatable {
287287
static std::size_t
288288
dynamicSize(const T& t,
289289
typename boost::enable_if<typename boost::is_pointer<T>>::type* = nullptr) {
290-
if (t == nullptr) {
291-
return 0;
292-
}
293-
return staticSize(*t) + dynamicSize(*t);
290+
return t == nullptr ? 0 : staticSize(*t) + dynamicSize(*t);
294291
}
295292

296293
//! Overload for std::shared_ptr.
297294
template<typename T>
298295
static std::size_t dynamicSize(const std::shared_ptr<T>& t) {
299-
if (!t) {
296+
if (t == nullptr) {
300297
return 0;
301298
}
302299
long uc = t.use_count();
303-
// Round up
304-
return (staticSize(*t) + dynamicSize(*t) + std::size_t(uc - 1)) / uc;
300+
// Note we add on sizeof(long) here to account for the memory
301+
// used by the shared reference count. Also, round up.
302+
return (sizeof(long) + staticSize(*t) + dynamicSize(*t) + std::size_t(uc - 1)) / uc;
303+
}
304+
305+
//! Overload for std::unique_ptr.
306+
template<typename T>
307+
static std::size_t dynamicSize(const std::unique_ptr<T>& t) {
308+
return t == nullptr ? 0 : staticSize(*t) + dynamicSize(*t);
305309
}
306310

307311
//! Overload for boost::array.
@@ -692,25 +696,40 @@ class CORE_EXPORT CMemoryDebug : private CNonInstantiatable {
692696
static void dynamicSize(const char* name,
693697
const std::shared_ptr<T>& t,
694698
CMemoryUsage::TMemoryUsagePtr mem) {
695-
if (t) {
699+
if (t != nullptr) {
696700
long uc = t.use_count();
697701
// If the pointer is shared by multiple users, each one
698702
// might count it, so divide by the number of users.
699703
// However, if only 1 user has it, do a full debug.
700704
if (uc == 1) {
701-
mem->addItem("shared_ptr", CMemory::staticSize(*t));
705+
// Note we add on sizeof(long) here to account for
706+
// the memory used by the shared reference count.
707+
mem->addItem("shared_ptr", sizeof(long) + CMemory::staticSize(*t));
702708
dynamicSize(name, *t, mem);
703709
} else {
704710
std::ostringstream ss;
705711
ss << "shared_ptr (x" << uc << ')';
706-
// Round up
707-
mem->addItem(ss.str(), (CMemory::staticSize(*t) +
712+
// Note we add on sizeof(long) here to account for
713+
// the memory used by the shared reference count.
714+
// Also, round up.
715+
mem->addItem(ss.str(), (sizeof(long) + CMemory::staticSize(*t) +
708716
CMemory::dynamicSize(*t) + std::size_t(uc - 1)) /
709717
uc);
710718
}
711719
}
712720
}
713721

722+
//! Overload for std::unique_ptr.
723+
template<typename T>
724+
static void dynamicSize(const char* name,
725+
const std::unique_ptr<T>& t,
726+
CMemoryUsage::TMemoryUsagePtr mem) {
727+
if (t != nullptr) {
728+
mem->addItem("ptr", CMemory::staticSize(*t));
729+
memory_detail::SDebugMemoryDynamicSize<T>::dispatch(name, *t, mem);
730+
}
731+
}
732+
714733
//! Overload for boost::array.
715734
template<typename T, std::size_t N>
716735
static void dynamicSize(const char* name,

include/maths/CChecksum.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,20 @@ class CChecksumImpl<BasicChecksum> {
158158
: CChecksumImpl<typename selector<T>::value>::dispatch(seed, *target);
159159
}
160160

161-
//! Checksum a pointer.
161+
//! Checksum a shared pointer.
162162
template<typename T>
163163
static uint64_t dispatch(uint64_t seed, const std::shared_ptr<T>& target) {
164164
return !target ? seed
165165
: CChecksumImpl<typename selector<T>::value>::dispatch(seed, *target);
166166
}
167167

168+
//! Checksum a unique pointer.
169+
template<typename T>
170+
static uint64_t dispatch(uint64_t seed, const std::unique_ptr<T>& target) {
171+
return !target ? seed
172+
: CChecksumImpl<typename selector<T>::value>::dispatch(seed, *target);
173+
}
174+
168175
//! Checksum a pair.
169176
template<typename U, typename V>
170177
static uint64_t dispatch(uint64_t seed, const std::pair<U, V>& target) {

include/maths/CClusterer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ class MATHS_EXPORT CClustererTypes {
125125
template<typename POINT>
126126
class CClusterer : public CClustererTypes {
127127
public:
128-
using TClustererPtr = std::shared_ptr<CClusterer>;
129128
using TPointVec = std::vector<POINT>;
130129
using TPointPrecise = typename SPromoted<POINT>::Type;
131130
using TPointPreciseVec = std::vector<TPointPrecise>;

include/maths/CClustererStateSerialiser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct SDistributionRestoreParams;
4343
//! to potential competitors.
4444
class MATHS_EXPORT CClustererStateSerialiser {
4545
public:
46-
using TClusterer1dPtr = std::shared_ptr<CClusterer1d>;
46+
using TClusterer1dPtr = std::unique_ptr<CClusterer1d>;
4747

4848
public:
4949
//! Construct the appropriate CClusterer sub-class from its state
@@ -73,7 +73,7 @@ class MATHS_EXPORT CClustererStateSerialiser {
7373
//! \note Sets \p ptr to NULL on failure.
7474
template<typename T, std::size_t N>
7575
bool operator()(const SDistributionRestoreParams& params,
76-
std::shared_ptr<CClusterer<CVectorNx1<T, N>>>& ptr,
76+
std::unique_ptr<CClusterer<CVectorNx1<T, N>>>& ptr,
7777
core::CStateRestoreTraverser& traverser) {
7878
return this->operator()(params, CClustererTypes::CDoNothing(),
7979
CClustererTypes::CDoNothing(), ptr, traverser);
@@ -87,7 +87,7 @@ class MATHS_EXPORT CClustererStateSerialiser {
8787
bool operator()(const SDistributionRestoreParams& params,
8888
const CClustererTypes::TSplitFunc& splitFunc,
8989
const CClustererTypes::TMergeFunc& mergeFunc,
90-
std::shared_ptr<CClusterer<CVectorNx1<T, N>>>& ptr,
90+
std::unique_ptr<CClusterer<CVectorNx1<T, N>>>& ptr,
9191
core::CStateRestoreTraverser& traverser) {
9292
std::size_t numResults(0);
9393

include/maths/CModelStateSerialiser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct SModelRestoreParams;
3434
//! compatibility in the future as the classes evolve.
3535
class MATHS_EXPORT CModelStateSerialiser {
3636
public:
37-
using TModelPtr = std::shared_ptr<CModel>;
37+
using TModelPtr = std::unique_ptr<CModel>;
3838

3939
public:
4040
//! Construct the appropriate CPrior sub-class from its state

include/maths/CMultimodalPrior.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,9 @@ namespace maths {
4949
//! point of view this is the composite pattern.
5050
class MATHS_EXPORT CMultimodalPrior : public CPrior {
5151
public:
52-
using TClustererPtr = std::shared_ptr<CClusterer1d>;
53-
using TPriorPtr = std::shared_ptr<CPrior>;
52+
using TClustererPtr = std::unique_ptr<CClusterer1d>;
53+
using TPriorPtr = std::unique_ptr<CPrior>;
5454
using TPriorPtrVec = std::vector<TPriorPtr>;
55-
using TPriorPtrVecItr = TPriorPtrVec::iterator;
56-
using TPriorPtrVecCItr = TPriorPtrVec::const_iterator;
5755
using TMeanVarAccumulator = CBasicStatistics::SSampleMeanVar<double>::TAccumulator;
5856
using TMeanVarAccumulatorVec = std::vector<TMeanVarAccumulator>;
5957

@@ -80,6 +78,9 @@ class MATHS_EXPORT CMultimodalPrior : public CPrior {
8078
double decayRate = 0.0);
8179

8280
//! Create from a collection of weights and priors.
81+
//!
82+
//! \note The priors are moved into place clearing the values in \p priors.
83+
//! \note This constructor doesn't support subsequent update of the prior.
8384
CMultimodalPrior(maths_t::EDataType dataType, double decayRate, TPriorPtrVec& priors);
8485

8586
//! Construct from part of a state document.
@@ -320,7 +321,7 @@ class MATHS_EXPORT CMultimodalPrior : public CPrior {
320321
CMultimodalPrior* m_Prior;
321322
};
322323

323-
using TMode = SMultimodalPriorMode<std::shared_ptr<CPrior>>;
324+
using TMode = SMultimodalPriorMode<TPriorPtr>;
324325
using TModeVec = std::vector<TMode>;
325326

326327
private:

include/maths/CMultimodalPriorMode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ struct SMultimodalPriorMode {
3636
SMultimodalPriorMode() : s_Index(0), s_Prior() {}
3737
SMultimodalPriorMode(std::size_t index, const PRIOR_PTR& prior)
3838
: s_Index(index), s_Prior(prior->clone()) {}
39+
SMultimodalPriorMode(std::size_t index, PRIOR_PTR&& prior)
40+
: s_Index(index), s_Prior(std::move(prior)) {}
3941

4042
//! Get the weight of this sample.
4143
double weight() const { return s_Prior->numberSamples(); }

include/maths/CMultivariateMultimodalPrior.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <maths/MathsTypes.h>
3333

3434
#include <boost/bind.hpp>
35+
#include <boost/make_unique.hpp>
3536
#include <boost/numeric/conversion/bounds.hpp>
3637
#include <boost/ref.hpp>
3738

@@ -50,10 +51,10 @@ namespace multivariate_multimodal_prior_detail {
5051

5152
using TSizeDoublePr = std::pair<size_t, double>;
5253
using TSizeDoublePr3Vec = core::CSmallVector<TSizeDoublePr, 3>;
53-
using TPriorPtr = std::shared_ptr<CMultivariatePrior>;
5454
using TDouble10Vec1Vec = CMultivariatePrior::TDouble10Vec1Vec;
5555
using TDouble10VecWeightsAry1Vec = CMultivariatePrior::TDouble10VecWeightsAry1Vec;
56-
using TMode = SMultimodalPriorMode<std::shared_ptr<CMultivariatePrior>>;
56+
using TPriorPtr = std::unique_ptr<CMultivariatePrior>;
57+
using TMode = SMultimodalPriorMode<TPriorPtr>;
5758
using TModeVec = std::vector<TMode>;
5859

5960
//! Implementation of a sample joint log marginal likelihood calculation.
@@ -134,7 +135,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
134135
using TMatrix = CSymmetricMatrixNxN<double, N>;
135136
using TMatrixVec = std::vector<TMatrix>;
136137
using TClusterer = CClusterer<TFloatPoint>;
137-
using TClustererPtr = std::shared_ptr<TClusterer>;
138+
using TClustererPtr = std::unique_ptr<TClusterer>;
138139
using TPriorPtrVec = std::vector<TPriorPtr>;
139140

140141
// Lift all overloads of into scope.
@@ -162,13 +163,13 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
162163

163164
//! Create from a collection of priors.
164165
//!
165-
//! \note The priors are shallow copied.
166+
//! \note The priors are moved into place clearing the values in \p priors.
166167
//! \note This constructor doesn't support subsequent update of the prior.
167168
CMultivariateMultimodalPrior(maths_t::EDataType dataType, TPriorPtrVec& priors)
168169
: CMultivariatePrior(dataType, 0.0) {
169170
m_Modes.reserve(priors.size());
170171
for (std::size_t i = 0u; i < priors.size(); ++i) {
171-
m_Modes.emplace_back(i, priors[i]);
172+
m_Modes.emplace_back(i, std::move(priors[i]));
172173
}
173174
}
174175

@@ -425,12 +426,12 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
425426
for (const auto& mode : m_Modes) {
426427
TUnivariatePriorPtrDoublePr prior(mode.s_Prior->univariate(marginalize, condition));
427428
if (prior.first == nullptr) {
428-
return TUnivariatePriorPtrDoublePr();
429+
return {};
429430
}
430431
if (prior.first->isNonInformative()) {
431432
continue;
432433
}
433-
modes.push_back(prior.first);
434+
modes.push_back(std::move(prior.first));
434435
weights.push_back(prior.second);
435436
maxWeight.add(weights.back());
436437
}
@@ -444,8 +445,8 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
444445
modes[i]->numberSamples(weights[i] / Z * modes[i]->numberSamples());
445446
}
446447

447-
return {TUnivariatePriorPtr(new CMultimodalPrior(this->dataType(),
448-
this->decayRate(), modes)),
448+
return {boost::make_unique<CMultimodalPrior>(this->dataType(),
449+
this->decayRate(), modes),
449450
Z > 0.0 ? maxWeight[0] + std::log(Z) : 0.0};
450451
}
451452

@@ -465,7 +466,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
465466
const TSizeDoublePr10Vec& condition) const {
466467

467468
if (N == 2) {
468-
return TPriorPtrDoublePr(TPriorPtr(this->clone()), 0.0);
469+
return {TPriorPtr(this->clone()), 0.0};
469470
}
470471

471472
std::size_t n = m_Modes.size();
@@ -484,7 +485,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
484485
if (prior.first->isNonInformative()) {
485486
continue;
486487
}
487-
modes.push_back(prior.first);
488+
modes.push_back(std::move(prior.first));
488489
weights.push_back(prior.second);
489490
maxWeight.add(weights.back());
490491
}
@@ -498,7 +499,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
498499
modes[i]->numberSamples(weights[i] / Z * modes[i]->numberSamples());
499500
}
500501

501-
return {TPriorPtr(new CMultivariateMultimodalPrior<2>(this->dataType(), modes)),
502+
return {boost::make_unique<CMultivariateMultimodalPrior<2>>(this->dataType(), modes),
502503
Z > 0.0 ? maxWeight[0] + std::log(Z) : 0.0};
503504
}
504505

@@ -905,7 +906,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
905906

906907
// Create the child modes.
907908
LOG_TRACE(<< "Creating mode with index " << leftSplitIndex);
908-
modes.emplace_back(leftSplitIndex, m_Prior->m_SeedPrior);
909+
modes.emplace_back(leftSplitIndex, TPriorPtr(m_Prior->m_SeedPrior->clone()));
909910
{
910911
TPointVec samples;
911912
if (!m_Prior->m_Clusterer->sample(
@@ -935,7 +936,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
935936
}
936937

937938
LOG_TRACE(<< "Creating mode with index " << rightSplitIndex);
938-
modes.emplace_back(rightSplitIndex, m_Prior->m_SeedPrior);
939+
modes.emplace_back(rightSplitIndex, TPriorPtr(m_Prior->m_SeedPrior->clone()));
939940
{
940941
TPointVec samples;
941942
if (!m_Prior->m_Clusterer->sample(
@@ -1025,7 +1026,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior {
10251026
MODE_TAG, TMode mode,
10261027
traverser.traverseSubLevel(boost::bind(
10271028
&TMode::acceptRestoreTraverser, &mode, boost::cref(params), _1)),
1028-
m_Modes.push_back(mode))
1029+
m_Modes.push_back(std::move(mode)))
10291030
RESTORE_SETUP_TEARDOWN(
10301031
NUMBER_SAMPLES_TAG, double numberSamples,
10311032
core::CStringUtils::stringToType(traverser.value(), numberSamples),

include/maths/CMultivariateMultimodalPriorFactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct SDistributionRestoreParams;
2525
//! \brief Factory for multivariate multimodal priors.
2626
class MATHS_EXPORT CMultivariateMultimodalPriorFactory {
2727
public:
28-
using TPriorPtr = std::shared_ptr<CMultivariatePrior>;
28+
using TPriorPtr = std::unique_ptr<CMultivariatePrior>;
2929

3030
public:
3131
//! Create a new non-informative multivariate normal prior.

0 commit comments

Comments
 (0)