Skip to content

Commit

Permalink
streamlined IConfigRecord emulation of old CNTK ConfigParameters by c…
Browse files Browse the repository at this point in the history
…hanging all key strings to wide strings. Likewise added two wide-string variants to ConfigParameters;

added a temporary fix to ProgressTracing that allows to not set the correct #epochs upfront (since BS can't do that);
added a first BS version of main()
  • Loading branch information
frankseide committed Nov 20, 2015
1 parent 736092f commit 75b781b
Show file tree
Hide file tree
Showing 10 changed files with 1,978 additions and 1,824 deletions.
4 changes: 4 additions & 0 deletions Common/Include/ProgressTracing.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ namespace Microsoft { namespace MSR { namespace CNTK {
auto & us = GetStaticInstance();
if (!us.m_enabled)
return false;
// in case we are not able to estimate, we will increase as needed
// BUGBUG: This is a workaround because in BrainScript we cannot estimate the total number of epochs without actually running the actions.
if (currentStep + 1 > us.m_totalNumberOfSteps)
us.m_totalNumberOfSteps = currentStep + 1;
// compute global progress
bool needToPrint = us.m_progressTracingTimer.ElapsedSeconds() > 0;// 10;
if (needToPrint)
Expand Down
52 changes: 23 additions & 29 deletions Common/Include/ScriptableObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,21 +343,29 @@ namespace Microsoft { namespace MSR { namespace ScriptableObjects {
// prettier access if config record is a pointer
const ConfigValuePtr & Get(const wstring & id) const { return operator[](id); } // e.g. confRecPtr->Get(L"message")

// access with default values
template<class ValueType> ValueType operator()(const wstring & id, const ValueType & defaultValue) const // e.g. confRec("message", "hello)
{
const auto * valp = Find(id);
return valp ? *valp : defaultValue;
}
inline const IConfigRecord & IConfigRecord::operator()(const wstring & id, const IConfigRecord & defaultValue) const // retrieve a nested ConfigRecord
{
const auto * valp = Find(id);
return valp ? valp->AsRef<IConfigRecord>() : defaultValue;
}
std::string operator()(const std::wstring & id, const char * defaultValue) const { return msra::strfun::utf8(operator()(id, (std::wstring)msra::strfun::utf16(defaultValue))); } // special case for narrow strings
std::wstring operator()(const std::wstring & id, const wchar_t * defaultValue) const { return operator()(id, wstring(defaultValue)); }

// -----------------------------------------------------------------------
// emulation of old CNTK config/NL
// This allows code written for CNTK config to simply turn ConfigParameters into a template parameter and accept an IConfigRecord.
// TODO: change all id args to wide strings, then update the code.
// -----------------------------------------------------------------------

const ConfigValuePtr & operator()(const char * id) const;
private:
const ConfigValuePtr * Find(const char * id) const;
public:
template<class ValueType> ValueType operator()(const char * id, const ValueType & defaultValue) const;
const IConfigRecord & operator()(const char * id, const IConfigRecord & defaultValue) const;
template<class T> std::vector<T> operator()(const char * id, const std::vector<T> & defaultValue) const;
std::string operator()(const char * id, const char * defaultValue) const;
std::wstring operator()(const char * id, const wchar_t * defaultValue) const;
bool ExistsCurrent(const char * id) const;
const ConfigValuePtr & operator()(const wstring & id) const;
template<class T> std::vector<T> operator()(const wstring & id, const std::vector<T> & defaultValue) const;
bool ExistsCurrent(const wstring & id) const;
static const IConfigRecord & Record();
template<class V> static const std::vector<typename V::value_type> & Array(const V & vec);

Expand Down Expand Up @@ -616,19 +624,8 @@ namespace Microsoft { namespace MSR { namespace ScriptableObjects {
// This allows code written for CNTK config to simply turn ConfigParameters into a template parameter and accept an IConfigRecord.
// -----------------------------------------------------------------------

inline const ConfigValuePtr & IConfigRecord::operator()(const char * id) const { wstring wid(id, id + strlen(id)); return operator[](wid); } // e.g. confRec("message")
/*private*/ inline const ConfigValuePtr * IConfigRecord::Find(const char * id) const { return Find(wstring(id, id + strlen(id))); }
template<class ValueType> inline ValueType IConfigRecord::operator()(const char * id, const ValueType & defaultValue) const // e.g. confRec("message", "hello)
{
const auto * valp = Find(id);
return valp ? *valp : defaultValue;
}
inline const IConfigRecord & IConfigRecord::operator()(const char * id, const IConfigRecord & defaultValue) const // retrieve a nested ConfigRecord
{
const auto * valp = Find(id);
return valp ? valp->AsRef<IConfigRecord>() : defaultValue;
}
template<class T> inline std::vector<T> IConfigRecord::operator()(const char * id, const std::vector<T> & defaultValue) const // retrieve an argvector (which derives from std::vector)
inline const ConfigValuePtr & IConfigRecord::operator()(const wstring & id) const { return operator[](id); } // e.g. confRec("message")
template<class T> inline std::vector<T> IConfigRecord::operator()(const wstring & id, const std::vector<T> & defaultValue) const // retrieve an argvector (which derives from std::vector)
{
const auto * valp = Find(id);
if (!valp)
Expand All @@ -643,19 +640,16 @@ namespace Microsoft { namespace MSR { namespace ScriptableObjects {
res[i] = arr.At(i, [](const wstring &){ LogicError("IConfigRecord: operator() for array failed unexpectedly."); });
return res;
}
inline std::string IConfigRecord::operator()(const char * id, const char * defaultValue) const { return msra::strfun::utf8(operator()(id, (std::wstring)msra::strfun::utf16(defaultValue))); } // special case for narrow strings
inline std::wstring IConfigRecord::operator()(const char * id, const wchar_t * defaultValue) const { return operator()(id, wstring(defaultValue)); } // special case for narrow id
inline bool IConfigRecord::ExistsCurrent(const char * id) const // this is inefficient, but we can optimize it if it ever turns out to be a problem. I rather think, this function is misguided. The name is bad, too.
inline bool IConfigRecord::ExistsCurrent(const wstring & id) const // this is inefficient, but we can optimize it if it ever turns out to be a problem. I rather think, this function is misguided. The name is bad, too.
{
wstring wid(id, id + strlen(id));
for (const auto & idIter : GetMemberIds()) // linear scan. Not using STL algorithm to avoid pulling in a big header at this level
if (idIter == wid)
if (idIter == id)
return true;
return false;
}
/*static*/ inline const IConfigRecord & IConfigRecord::Record() // empty record to be passed as a default to operator() when retrieving a nested ConfigRecord
{
static struct EmptyConfigRecord : public ScriptableObjects::IConfigRecord
static struct EmptyConfigRecord : public IConfigRecord
{
virtual const ScriptableObjects::ConfigValuePtr & operator[](const wstring &) const override final { InvalidArgument("EmptyConfigRecord: Attempted to return a value from the empty record."); }
virtual const ScriptableObjects::ConfigValuePtr * Find(const wstring &) const override final { return nullptr; }
Expand Down
5 changes: 3 additions & 2 deletions Common/Include/commandArgUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@ class ConfigParameters: public ConfigParser, public ConfigDictionary
{
return (find(name) != end());
}
bool ExistsCurrent(const wchar_t * name) const { return ExistsCurrent(string(name, name + wcslen(name))); }

// dict(name, default) for strings
ConfigValue operator()(const std::wstring& name,
Expand Down Expand Up @@ -930,14 +931,14 @@ class ConfigParameters: public ConfigParser, public ConfigDictionary

// version for defaults with types
template<typename Type>
Type operator()(const char * name,
Type operator()(const wchar_t * name,
const Type & defaultValue) const
{
// find the value
// TODO: unify with the Find() function below
for (auto * dict = this; dict; dict = dict->m_parent)
{
auto iter = dict->find(name);
auto iter = dict->find(string(name, name + wcslen(name)));
if (iter != dict->end())
{
if (iter->second == "default")
Expand Down
Loading

0 comments on commit 75b781b

Please sign in to comment.