/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
- * David van der Spoel, Berk Hess, Erik Lindahl, and including many
- * others, as listed in the AUTHORS file in the top-level source
- * directory and at http://www.gromacs.org.
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
*
* GROMACS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* \author Teemu Murtola <teemu.murtola@gmail.com>
* \ingroup module_analysisdata
*/
+#include "gmxpre.h"
+
#include "datastorage.h"
#include <algorithm>
{
return isMultipoint() && storageLimit_ == 0 && pendingLimit_ == 1;
}
+ /*! \brief
+ * Returns whether data needs to be stored at all.
+ *
+ * This is used to optimize multipoint handling for parallel cases
+ * (where shouldNotifyImmediately() returns false),
+ * where it is not necessary to store even a single frame.
+ *
+ * \todo
+ * This could be extended to non-multipoint data as well.
+ *
+ * Does not throw.
+ */
+ bool needStorage() const
+ {
+ return storageLimit_ > 0 || (pendingLimit_ > 1 && modules_->hasSerialModules());
+ }
/*! \brief
* Calls notification methods for new frames.
*
*
* Should always be at least one.
*
+ * \todo
+ * Get rid of this alltogether, as it is no longer used much.
+ *
* \see AnalysisDataStorage::startFrame()
*/
int pendingLimit_;
* AnalysisDataStorageFrameImpl declaration
*/
-/*! \internal \brief
+/*! \internal
+ * \brief
* Internal representation for a single stored frame.
*
* It is implemented such that the frame header is always valid, i.e.,
GMX_RELEASE_ASSERT(storedFrame.frameIndex() == index,
"Inconsistent internal frame indexing");
builders_.push_back(storedFrame.finishFrame(isMultipoint()));
+ modules_->notifyParallelFrameFinish(storedFrame.header());
if (shouldNotifyImmediately())
{
++firstUnnotifiedIndex_;
AnalysisDataStorageFrameData::addPointSet(int dataSetIndex, int firstColumn,
ValueIterator begin, ValueIterator end)
{
- const int valueCount = end - begin;
+ const int valueCount = end - begin;
+ AnalysisDataPointSetInfo pointSetInfo(0, valueCount,
+ dataSetIndex, firstColumn);
+ AnalysisDataPointSetRef pointSet(header(), pointSetInfo,
+ constArrayRefFromVector<AnalysisDataValue>(begin, end));
+ storageImpl().modules_->notifyParallelPointsAdd(pointSet);
if (storageImpl().shouldNotifyImmediately())
{
- AnalysisDataPointSetInfo pointSetInfo(0, valueCount,
- dataSetIndex, firstColumn);
- storageImpl().modules_->notifyPointsAdd(
- AnalysisDataPointSetRef(header(), pointSetInfo,
- AnalysisDataValuesRef(begin, end)));
+ storageImpl().modules_->notifyPointsAdd(pointSet);
}
- else
+ else if (storageImpl().needStorage())
{
pointSets_.push_back(
AnalysisDataPointSetInfo(values_.size(), valueCount,
"Point sets created for non-multipoint data");
values_ = builder_->values_;
builder_->clearValues();
+ for (int i = 0; i < pointSetCount(); ++i)
+ {
+ storageImpl().modules_->notifyParallelPointsAdd(pointSet(i));
+ }
}
else
{
"Invalid point set index");
return AnalysisDataPointSetRef(
header_, pointSets_[index],
- AnalysisDataValuesRef(values_.begin(), values_.end()));
+ constArrayRefFromVector<AnalysisDataValue>(values_.begin(), values_.end()));
}
} // namespace internal
}
-void
-AnalysisDataStorage::setParallelOptions(const AnalysisDataParallelOptions &opt)
-{
- impl_->pendingLimit_ = 2 * opt.parallelizationFactor() - 1;
-}
-
-
int
AnalysisDataStorage::frameCount() const
{
impl_->modules_ = modules;
if (!impl_->storeAll())
{
- impl_->extendBuffer(impl_->storageLimit_ + impl_->pendingLimit_ + 1);
+ // 2 = pending limit (1) + 1
+ impl_->extendBuffer(impl_->storageLimit_ + 2);
+ }
+}
+
+
+void
+AnalysisDataStorage::startParallelDataStorage(
+ AbstractAnalysisData *data,
+ AnalysisDataModuleManager *modules,
+ const AnalysisDataParallelOptions &options)
+{
+ const int pendingLimit = options.parallelizationFactor();
+ impl_->pendingLimit_ = pendingLimit;
+ modules->notifyParallelDataStart(data, options);
+ // Data needs to be set before calling extendBuffer()
+ impl_->data_ = data;
+ impl_->modules_ = modules;
+ if (!impl_->storeAll())
+ {
+ impl_->extendBuffer(impl_->storageLimit_ + pendingLimit + 1);
}
}
GMX_RELEASE_ASSERT(storedFrame->frameIndex() == header.index(),
"Inconsistent internal frame indexing");
storedFrame->startFrame(header, impl_->getFrameBuilder());
+ impl_->modules_->notifyParallelFrameStart(header);
if (impl_->shouldNotifyImmediately())
{
impl_->modules_->notifyFrameStart(header);