mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-09-11 11:25:40 +03:00
Enable parallelisation
git-svn-id: https://mosesdecoder.svn.sourceforge.net/svnroot/mosesdecoder/branches/mira-mtm5@3584 1f5c12ca-751b-0410-a591-d2e778427230
This commit is contained in:
parent
03419ac02a
commit
a4b4ba15d7
12
config.h.in
12
config.h.in
@ -3,9 +3,15 @@
|
||||
/* define if the Boost library is available */
|
||||
#undef HAVE_BOOST
|
||||
|
||||
/* define if the Boost::MPI library is available */
|
||||
#undef HAVE_BOOST_MPI
|
||||
|
||||
/* define if the Boost::PROGRAM_OPTIONS library is available */
|
||||
#undef HAVE_BOOST_PROGRAM_OPTIONS
|
||||
|
||||
/* define if the Boost::Serialization library is available */
|
||||
#undef HAVE_BOOST_SERIALIZATION
|
||||
|
||||
/* define if the Boost::Thread library is available */
|
||||
#undef HAVE_BOOST_THREAD
|
||||
|
||||
@ -61,6 +67,9 @@
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define if compiling with MPI. */
|
||||
#undef MPI_ENABLED
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
@ -76,9 +85,6 @@
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
|
19
configure.in
19
configure.in
@ -19,6 +19,25 @@ AX_XMLRPC_C
|
||||
AX_BOOST_BASE([1.37.0])
|
||||
AX_BOOST_PROGRAM_OPTIONS
|
||||
|
||||
ac_have_mpi=no
|
||||
AC_ARG_WITH(mpi,
|
||||
AC_HELP_STRING([--with-mpi],
|
||||
[Force compilation with MPI]),
|
||||
[ if test $withval != no ; then
|
||||
ac_have_mpi=yes
|
||||
fi ] )
|
||||
if test $ac_have_mpi = yes ; then
|
||||
AC_PATH_PROG(CXX, mpic++, none)
|
||||
if test $CXX = none ; then
|
||||
AC_MSG_ERROR([Cannot locate MPI compiler drivers])
|
||||
fi
|
||||
AX_BOOST_SERIALIZATION
|
||||
AX_BOOST_MPI
|
||||
AC_DEFINE(MPI_ENABLED,1,[Define if compiling with MPI.])
|
||||
CPPFLAGS="$CPPFLAGS -DMPI_ENABLE=1"
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_WITH(protobuf,
|
||||
[AC_HELP_STRING([--with-protobuf=PATH], [(optional) path to Google protobuf])],
|
||||
[with_protobuf=$withval],
|
||||
|
132
mira/Main.cpp
132
mira/Main.cpp
@ -17,12 +17,17 @@ License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
***********************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#ifdef MPI_ENABLE
|
||||
#include <boost/mpi.hpp>
|
||||
namespace mpi = boost::mpi;
|
||||
#endif
|
||||
|
||||
#include "FeatureVector.h"
|
||||
#include "StaticData.h"
|
||||
@ -49,19 +54,43 @@ bool loadSentences(const string& filename, vector<string>& sentences) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct RandomIndex {
|
||||
ptrdiff_t operator() (ptrdiff_t max) {
|
||||
return static_cast<ptrdiff_t>(rand() % max);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
size_t rank = 0; size_t size = 1;
|
||||
#ifdef MPI_ENABLE
|
||||
mpi::environment env(argc,argv);
|
||||
mpi::communicator world;
|
||||
rank = world.rank();
|
||||
size = world.size();
|
||||
#endif
|
||||
cerr << "Rank: " << rank << " Size: " << size << endl;
|
||||
|
||||
bool help;
|
||||
int verbosity;
|
||||
string mosesConfigFile;
|
||||
string inputFile;
|
||||
vector<string> referenceFiles;
|
||||
size_t epochs;
|
||||
string learner;
|
||||
bool shuffle = true;
|
||||
size_t mixFrequency;
|
||||
size_t weightDumpFrequency;
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("help",po::value( &help )->zero_tokens()->default_value(false), "Print this help message and exit")
|
||||
("config,f",po::value<string>(&mosesConfigFile),"Moses ini file")
|
||||
("verbosity,v", po::value<int>(&verbosity)->default_value(0), "Verbosity level")
|
||||
("input-file,i",po::value<string>(&inputFile),"Input file containing tokenised source")
|
||||
("reference-files,r", po::value<vector<string> >(&referenceFiles), "Reference translation files for training");
|
||||
("reference-files,r", po::value<vector<string> >(&referenceFiles), "Reference translation files for training")
|
||||
("epochs,e", po::value<size_t>(&epochs)->default_value(1), "Number of epochs")
|
||||
("learner,l", po::value<string>(&learner)->default_value("mira"), "Learning algorithm")
|
||||
("mix-frequency", po::value<size_t>(&mixFrequency)->default_value(1), "How often per epoch to mix weights, when using mpi")
|
||||
("weight-dump-frequency", po::value<size_t>(&weightDumpFrequency)->default_value(1), "How often per epoch to dump weights");
|
||||
|
||||
po::options_description cmdline_options;
|
||||
cmdline_options.add(desc);
|
||||
@ -93,6 +122,20 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//FIXME: Make these configurable
|
||||
float miraLowerBound = 0;
|
||||
float miraUpperBound = 1;
|
||||
|
||||
Optimiser* optimiser = NULL;
|
||||
if (learner == "mira") {
|
||||
cerr << "Optimising using Mira" << endl;
|
||||
optimiser = new MiraOptimiser(miraLowerBound, miraUpperBound);
|
||||
} else if (learner == "perceptron") {
|
||||
cerr << "Optimising using Perceptron" << endl;
|
||||
optimiser = new Perceptron();
|
||||
} else {
|
||||
cerr << "Error: Unknown optimiser: " << learner << endl;
|
||||
}
|
||||
|
||||
|
||||
//load input and references
|
||||
@ -118,24 +161,51 @@ int main(int argc, char** argv) {
|
||||
//initialise moses
|
||||
initMoses(mosesConfigFile, verbosity);//, argc, argv);
|
||||
MosesDecoder* decoder = new MosesDecoder(referenceSentences) ;
|
||||
|
||||
//Optionally shuffle the sentences
|
||||
vector<size_t> order;
|
||||
if (rank == 0) {
|
||||
for (size_t i = 0; i < inputSentences.size(); ++i) {
|
||||
order.push_back(i);
|
||||
}
|
||||
if (shuffle) {
|
||||
RandomIndex rindex;
|
||||
random_shuffle(order.begin(), order.end(), rindex);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MPI_ENABLE
|
||||
mpi::broadcast(world,order,0);
|
||||
#endif
|
||||
|
||||
//Create the shards
|
||||
vector<size_t> shard;
|
||||
float shardSize = (float)(order.size()) / size;
|
||||
VERBOSE(1, "Shard size: " << shardSize << endl);
|
||||
size_t shardStart = (size_t)(shardSize * rank);
|
||||
size_t shardEnd = (size_t)(shardSize * (rank+1));
|
||||
if (rank == size-1) shardEnd = order.size();
|
||||
VERBOSE(1,"Rank: " << rank << " Shard start: " << shardStart << " Shard end: " << shardEnd << endl);
|
||||
shard.resize(shardSize);
|
||||
copy(order.begin() + shardStart, order.begin() + shardEnd, shard.begin());
|
||||
|
||||
|
||||
|
||||
//Main loop:
|
||||
ScoreComponentCollection cumulativeWeights;
|
||||
Optimiser* optimiser = new Perceptron();
|
||||
size_t epochs = 1;
|
||||
size_t modelHypoCount = 10;
|
||||
size_t hopeHypoCount = 10;
|
||||
size_t fearHypoCount = 10;
|
||||
size_t iterations;
|
||||
size_t iterations = 0;
|
||||
|
||||
|
||||
for (size_t epoch = 0; epoch < epochs; ++epoch) {
|
||||
//TODO: batch
|
||||
for (size_t sid = 0; sid < inputSentences.size(); ++sid) {
|
||||
++iterations;
|
||||
const string& input = inputSentences[sid];
|
||||
const vector<string>& refs = referenceSentences[sid];
|
||||
//TODO: batching
|
||||
size_t shardPosition = 0;
|
||||
for (vector<size_t>::const_iterator sid = shard.begin();
|
||||
sid != shard.end(); ++sid) {
|
||||
const string& input = inputSentences[*sid];
|
||||
const vector<string>& refs = referenceSentences[*sid];
|
||||
|
||||
vector<vector<ScoreComponentCollection > > allScores(1);
|
||||
vector<vector<float> > allLosses(1);
|
||||
@ -143,7 +213,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// MODEL
|
||||
decoder->getNBest(input,
|
||||
sid,
|
||||
*sid,
|
||||
modelHypoCount,
|
||||
0.0,
|
||||
1.0,
|
||||
@ -155,7 +225,7 @@ int main(int argc, char** argv) {
|
||||
size_t oraclePos = allScores.size();
|
||||
vector<const Word*> oracle =
|
||||
decoder->getNBest(input,
|
||||
sid,
|
||||
*sid,
|
||||
modelHypoCount,
|
||||
1.0,
|
||||
1.0,
|
||||
@ -167,7 +237,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// FEAR
|
||||
decoder->getNBest(input,
|
||||
sid,
|
||||
*sid,
|
||||
modelHypoCount,
|
||||
-1.0,
|
||||
1.0,
|
||||
@ -190,17 +260,45 @@ int main(int argc, char** argv) {
|
||||
, oracleScores);
|
||||
|
||||
//update moses weights
|
||||
mosesWeights.L1Normalise();
|
||||
decoder->setWeights(mosesWeights);
|
||||
|
||||
//history (for approx doc bleu)
|
||||
decoder->updateHistory(oracle);
|
||||
|
||||
cumulativeWeights.PlusEquals(mosesWeights);
|
||||
cerr << "Cumulative weights: " << cumulativeWeights << endl;
|
||||
cerr << "Averaging: TODO " << endl;
|
||||
|
||||
|
||||
decoder->cleanup();
|
||||
|
||||
++shardPosition;
|
||||
++iterations;
|
||||
|
||||
//mix weights?
|
||||
#ifdef MPI_ENABLE
|
||||
if (shardPosition % (shard.size() / mixFrequency) == 0) {
|
||||
ScoreComponentCollection averageWeights;
|
||||
VERBOSE(1, "Rank: " << rank << "Before mixing: " << mosesWeights << endl);
|
||||
mpi::reduce(world,mosesWeights,averageWeights,SCCPlus(),0);
|
||||
if (rank == 0) {
|
||||
averageWeights.MultiplyEquals(1.0f/size);
|
||||
VERBOSE(1, "After mixing: " << averageWeights << endl);
|
||||
}
|
||||
mpi::broadcast(world,averageWeights,0);
|
||||
decoder->setWeights(averageWeights);
|
||||
}
|
||||
#endif
|
||||
|
||||
//dump weights?
|
||||
if (shardPosition % (shard.size() / weightDumpFrequency) == 0) {
|
||||
ScoreComponentCollection totalWeights(cumulativeWeights);
|
||||
#ifdef MPI_ENABLE
|
||||
//average across processes
|
||||
mpi::reduce(world,cumulativeWeights,totalWeights,SCCPlus(),0);
|
||||
#endif
|
||||
if (rank == 0) {
|
||||
cout << "WEIGHTS " << iterations << " ";
|
||||
totalWeights.L1Normalise();
|
||||
cout << totalWeights << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,4 +9,4 @@ mira_SOURCES = \
|
||||
AM_CPPFLAGS = -W -Wall -Wno-unused -ffor-scope -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -I$(top_srcdir)/moses/src -I$(top_srcdir)/moses-chart/src $(BOOST_CPPFLAGS)
|
||||
|
||||
|
||||
mira_LDADD = -L$(top_srcdir)/moses/src -L$(top_srcdir)/moses-chart/src -lmoses -lmoses-chart $(BOOST_LDFLAGS) $(BOOST_SERIALIZATION_LIB) $(BOOST_PROGRAM_OPTIONS_LIB) $(BOOST_MPI_LIB) -L$(top_srcdir)/OnDiskPt/src -lOnDiskPt
|
||||
mira_LDADD = $(top_builddir)/moses/src/libmoses.la -L$(top_srcdir)/moses/src -L$(top_srcdir)/moses-chart/src -lmoses -lmoses-chart $(BOOST_LDFLAGS) $(BOOST_SERIALIZATION_LIB) $(BOOST_PROGRAM_OPTIONS_LIB) $(BOOST_MPI_LIB) -L$(top_srcdir)/OnDiskPt/src -lOnDiskPt
|
||||
|
@ -333,7 +333,7 @@ namespace Moses {
|
||||
FValue FVector::l1norm() const {
|
||||
FValue norm = 0;
|
||||
for (const_iterator i = cbegin(); i != cend(); ++i) {
|
||||
if (!(i->second) && i->first == DEFAULT_NAME) {
|
||||
if ((i->second) && i->first == DEFAULT_NAME) {
|
||||
throw runtime_error("Cannot take l1norm with non-zero default values");
|
||||
}
|
||||
norm += abs(i->second);
|
||||
@ -344,7 +344,7 @@ namespace Moses {
|
||||
FValue FVector::sum() const {
|
||||
FValue sum = 0;
|
||||
for (const_iterator i = cbegin(); i != cend(); ++i) {
|
||||
if (!(i->second) && i->first == DEFAULT_NAME) {
|
||||
if ((i->second) && i->first == DEFAULT_NAME) {
|
||||
throw runtime_error("Cannot take sum with non-zero default values");
|
||||
}
|
||||
sum += i->second;
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#ifdef MPI_ENABLED
|
||||
#ifdef MPI_ENABLE
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
@ -179,7 +179,7 @@ namespace Moses {
|
||||
/** printing */
|
||||
std::ostream& print(std::ostream& out) const;
|
||||
|
||||
#ifdef MPI_ENABLED
|
||||
#ifdef MPI_ENABLE
|
||||
friend class boost::serialization::access;
|
||||
#endif
|
||||
|
||||
@ -194,13 +194,13 @@ namespace Moses {
|
||||
FNVmap m_features;
|
||||
size_t m_size;
|
||||
|
||||
#ifdef MPI_ENABLED
|
||||
#ifdef MPI_ENABLE
|
||||
//serialization
|
||||
template<class Archive>
|
||||
void save(Archive &ar, const unsigned int version) const {
|
||||
std::vector<std::string> names;
|
||||
std::vector<FValue> values;
|
||||
for (const_iterator i = begin(); i != end(); ++i) {
|
||||
for (const_iterator i = cbegin(); i != cend(); ++i) {
|
||||
std::ostringstream ostr;
|
||||
ostr << i->first;
|
||||
names.push_back(ostr.str());
|
||||
|
@ -10,6 +10,10 @@ ScoreComponentCollection::ScoreComponentCollection()
|
||||
, m_sim(&StaticData::Instance().GetScoreIndexManager())
|
||||
{}
|
||||
|
||||
const ScoreIndexManager* ScoreComponentCollection::GetSim() {
|
||||
return &(StaticData::Instance().GetScoreIndexManager());
|
||||
}
|
||||
|
||||
float ScoreComponentCollection::GetWeightedScore() const
|
||||
{
|
||||
float ret = InnerProduct(StaticData::Instance().GetAllWeights());
|
||||
@ -119,6 +123,10 @@ void StaticData::SetAllWeightsScoreComponentCollection(const ScoreComponentColle
|
||||
|
||||
}
|
||||
|
||||
void ScoreComponentCollection::L1Normalise() {
|
||||
m_scores /= m_scores.l1norm();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,6 +25,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include <numeric>
|
||||
#include <cassert>
|
||||
|
||||
#ifdef MPI_ENABLE
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#endif
|
||||
|
||||
#include "LMList.h"
|
||||
#include "ScoreProducer.h"
|
||||
#include "ScoreIndexManager.h"
|
||||
@ -32,9 +37,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include "TypeDef.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
namespace Moses
|
||||
{
|
||||
|
||||
|
||||
/*** An unweighted collection of scores for a translation or step in a translation.
|
||||
*
|
||||
* In the factored phrase-based models that are implemented by moses, there are a set of
|
||||
@ -57,6 +64,7 @@ class ScoreComponentCollection {
|
||||
friend std::ostream& operator<<(std::ostream& os, const ScoreComponentCollection& rhs);
|
||||
friend class ScoreIndexManager;
|
||||
private:
|
||||
const ScoreIndexManager* GetSim();
|
||||
FVector m_scores;
|
||||
const ScoreIndexManager* m_sim;
|
||||
|
||||
@ -203,7 +211,42 @@ public:
|
||||
|
||||
void ZeroAllLM(const LMList& lmList);
|
||||
void PlusEqualsAllLM(const LMList& lmList, const ScoreComponentCollection& rhs);
|
||||
void L1Normalise();
|
||||
|
||||
#ifdef MPI_ENABLE
|
||||
public:
|
||||
friend class boost::serialization::access;
|
||||
|
||||
private:
|
||||
//serialization
|
||||
template<class Archive>
|
||||
void save(Archive &ar, const unsigned int version) const {
|
||||
ar << m_scores;
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive &ar, const unsigned int version) {
|
||||
ar >> m_scores;
|
||||
m_sim = GetSim();
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct SCCPlus {
|
||||
ScoreComponentCollection operator()
|
||||
(const ScoreComponentCollection& lhs,
|
||||
const ScoreComponentCollection& rhs) {
|
||||
ScoreComponentCollection sum(lhs);
|
||||
sum.PlusEquals(rhs);
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user