Commit 57564d00 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

#913 Introduce a debug scheme to track whether a call to UpdateGhosts is required or not.

parent 0389b152
......@@ -894,6 +894,9 @@
BE6805D91BA3112400ED40DF /* LocalLagrangianInterpolator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE6805D61BA3112400ED40DF /* LocalLagrangianInterpolator.cpp */; };
BE6805DA1BA3112400ED40DF /* LocalLagrangianInterpolator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BE6805D71BA3112400ED40DF /* LocalLagrangianInterpolator.hpp */; };
BE6805DB1BA3112400ED40DF /* LocalLagrangianInterpolator.hxx in Headers */ = {isa = PBXBuildFile; fileRef = BE6805D81BA3112400ED40DF /* LocalLagrangianInterpolator.hxx */; };
BE6864751D80A8BF0049F114 /* CheckUpdateGhostManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE6864721D80A8BF0049F114 /* CheckUpdateGhostManager.cpp */; };
BE6864761D80A8BF0049F114 /* CheckUpdateGhostManager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BE6864731D80A8BF0049F114 /* CheckUpdateGhostManager.hpp */; };
BE6864771D80A8BF0049F114 /* CheckUpdateGhostManager.hxx in Headers */ = {isa = PBXBuildFile; fileRef = BE6864741D80A8BF0049F114 /* CheckUpdateGhostManager.hxx */; };
BE68FE041B14B85C00080163 /* TransientSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE68FE011B14B85C00080163 /* TransientSource.cpp */; };
BE68FE051B14B85C00080163 /* TransientSource.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BE68FE021B14B85C00080163 /* TransientSource.hpp */; };
BE6A109E1B18923100F19349 /* LameMu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE6A109B1B18923100F19349 /* LameMu.cpp */; };
......@@ -5068,6 +5071,9 @@
BE6805D61BA3112400ED40DF /* LocalLagrangianInterpolator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalLagrangianInterpolator.cpp; sourceTree = "<group>"; };
BE6805D71BA3112400ED40DF /* LocalLagrangianInterpolator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LocalLagrangianInterpolator.hpp; sourceTree = "<group>"; };
BE6805D81BA3112400ED40DF /* LocalLagrangianInterpolator.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LocalLagrangianInterpolator.hxx; sourceTree = "<group>"; };
BE6864721D80A8BF0049F114 /* CheckUpdateGhostManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CheckUpdateGhostManager.cpp; sourceTree = "<group>"; };
BE6864731D80A8BF0049F114 /* CheckUpdateGhostManager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CheckUpdateGhostManager.hpp; sourceTree = "<group>"; };
BE6864741D80A8BF0049F114 /* CheckUpdateGhostManager.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CheckUpdateGhostManager.hxx; sourceTree = "<group>"; };
BE68FE011B14B85C00080163 /* TransientSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TransientSource.cpp; path = Parameter/Source/Private/TransientSource.cpp; sourceTree = "<group>"; };
BE68FE021B14B85C00080163 /* TransientSource.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TransientSource.hpp; path = Parameter/Source/Private/TransientSource.hpp; sourceTree = "<group>"; };
BE6A109B1B18923100F19349 /* LameMu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LameMu.cpp; sourceTree = "<group>"; };
......@@ -8001,6 +8007,9 @@
children = (
BE4AB0121A233FF4002B554E /* VectorHelper.cpp */,
BE4AB0131A233FF4002B554E /* VectorHelper.hpp */,
BE6864721D80A8BF0049F114 /* CheckUpdateGhostManager.cpp */,
BE6864731D80A8BF0049F114 /* CheckUpdateGhostManager.hpp */,
BE6864741D80A8BF0049F114 /* CheckUpdateGhostManager.hxx */,
);
path = Private;
sourceTree = "<group>";
......@@ -11771,6 +11780,7 @@
BE90E1B91A24929A00CCAFDE /* Print.hpp in Headers */,
BE5B6F8D1C3C16E9004A0284 /* MatrixOperations.hxx in Headers */,
BEDEB92C1C3C073100B1C71B /* Solver.hpp in Headers */,
BE6864761D80A8BF0049F114 /* CheckUpdateGhostManager.hpp in Headers */,
BEEABA641A49CB5A00A875C6 /* CommandLineOptions.hpp in Headers */,
BE6F5A2D1A8396840076DF90 /* HappyHeartPetscVector.hxx in Headers */,
BE90E1801A24929A00CCAFDE /* OpsFunction.hpp in Headers */,
......@@ -11865,6 +11875,7 @@
BE90E17C1A24929A00CCAFDE /* Base.hpp in Headers */,
BE76F2621D7D60660061B50E /* GlobalVectorTemporaryStorage.hpp in Headers */,
BE90E1D61A2492AA00CCAFDE /* String.hpp in Headers */,
BE6864771D80A8BF0049F114 /* CheckUpdateGhostManager.hxx in Headers */,
BE76F2701D7D61540061B50E /* GlobalVectorTemporaryAccess.hxx in Headers */,
BE90E1A11A24929A00CCAFDE /* Comm.hpp in Headers */,
BE90E1791A24926E00CCAFDE /* Singleton.hxx in Headers */,
......@@ -14136,6 +14147,7 @@
BE2DCB521C7477430070090E /* libmesh6.c in Sources */,
BE90E1941A24929A00CCAFDE /* TimeKeep.cpp in Sources */,
BE90E1611A24926E00CCAFDE /* Exception.cpp in Sources */,
BE6864751D80A8BF0049F114 /* CheckUpdateGhostManager.cpp in Sources */,
BE41A8C71A24AA35004E4312 /* Parmetis.cpp in Sources */,
BE90E18E1A24929A00CCAFDE /* File.cpp in Sources */,
);
......@@ -16775,6 +16787,7 @@
"_LIBCPP_DEBUG2=0",
SELDON_WITH_COMPILED_LIBRARY,
SELDON_WITHOUT_TO_STR_CHECKDIM,
HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE,
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
......@@ -13,7 +13,7 @@
# include "Utilities/Containers/Tuple.hpp"
# include "ThirdParty/Wrappers/Petsc/Print.hpp"
# include "ThirdParty/Wrappers/Petsc/Vector/Private/CheckUpdateGhostManager.hpp"
# include "Core/InputParameterData/SetFromInputParameterData.hpp"
# include "Core/NumberingSubset/Internal/NumberingSubsetManager.hpp"
......
......@@ -108,6 +108,11 @@ namespace HappyHeart
Wrappers::Petsc::PrintMessageOnFirstProcessor("%s==============================================================\n",
mpi, __FILE__, __LINE__, date_time);
#ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
if (mpi.template Nprocessor<int>() > 1)
::HappyHeart::Wrappers::Petsc::Internal::CheckUpdateGhostManager::GetInstance().Print();
#endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
}
......
......@@ -26,6 +26,7 @@ third_party_src_keep_warnings = Split('''
./Wrappers/Petsc/Vector/AccessVectorContent.cpp
./Wrappers/Petsc/Vector/Private/VectorHelper.cpp
./Wrappers/Petsc/Vector/Vector.cpp
./Wrappers/Petsc/Vector/Private/CheckUpdateGhostManager.cpp
./Wrappers/Petsc/Viewer.cpp
./Wrappers/Seldon/HappyHeartPetscVector.cpp
./Wrappers/Seldon/MatrixOperations.cpp
......
......@@ -275,6 +275,8 @@ namespace HappyHeart
int error_code = ::MatMultAdd(matrix.Internal(), v1.Internal(), v2.Internal(), v3.Internal());
if (error_code)
throw ExceptionNS::Exception(error_code, "MatMultAdd", invoking_file, invoking_line);
v3.UpdateGhosts(invoking_file, invoking_line, do_update_ghost);
}
......
//! \file
//
//
// CheckUpdateGhostManager.cpp
// HappyHeart
//
// Created by Sebastien Gilles on 07/09/16.
// Copyright © 2016 Inria. All rights reserved.
//
#ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
# include <iostream>
# include "ThirdParty/Wrappers/Petsc/Vector/Private/CheckUpdateGhostManager.hpp"
namespace HappyHeart
{
namespace Wrappers
{
namespace Petsc
{
namespace Internal
{
const std::string& CheckUpdateGhostManager::ClassName()
{
static std::string ret("CheckUpdateGhostManager");
return ret;
}
void CheckUpdateGhostManager::UnneededCall(const std::string& file, unsigned int line)
{
decltype(auto) unneeded_calls = GetNonCstUnneededCalls();
auto&& pair = std::make_pair(file, line);
const auto it = unneeded_calls.find(pair);
if (it == unneeded_calls.cend())
unneeded_calls.insert(pair);
}
void CheckUpdateGhostManager::NeededCall(const std::string& file, unsigned int line)
{
decltype(auto) unneeded_calls = GetNonCstUnneededCalls();
auto&& pair = std::make_pair(file, line);
const auto it = unneeded_calls.find(pair);
if (it != unneeded_calls.cend())
unneeded_calls.erase(it);
}
void CheckUpdateGhostManager::Print() const
{
decltype(auto) unneeded_calls = GetUnneededCalls();
std::cout << "CheckUpdateGhostManager DESTRUCTOR" << std::endl;
if (unneeded_calls.empty())
std::cout << "[NOTE] No unneeded call to UpdateGhosts()." << std::endl;
else
{
std::cout << "[WARNING] The following calls to UpdateGhosts() were probably unneeded:"
<< std::endl;
for (const auto& item : unneeded_calls_)
std::cout << "\t" << item.first << ", line " << item.second << std::endl;
}
}
} // namespace Internal
} // namespace Petsc
} // namespace Wrappers
} // namespace HappyHeart
#endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
//! \file
//
//
// CheckUpdateGhostManager.hpp
// HappyHeart
//
// Created by Sebastien Gilles on 07/09/16.
// Copyright © 2016 Inria. All rights reserved.
//
#ifndef HAPPY_HEART_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_PRIVATE_x_CHECK_UPDATE_GHOST_MANAGER_HPP_
# define HAPPY_HEART_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_PRIVATE_x_CHECK_UPDATE_GHOST_MANAGER_HPP_
# ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
# include <memory>
# include <vector>
# include <set>
# include "Utilities/Singleton/Singleton.hpp"
namespace HappyHeart
{
namespace Wrappers
{
namespace Petsc
{
namespace Internal
{
/*!
* \brief Helper object used to detect unneeded calls to UpdateGhosts().
*
* This object is to use only in debug mode when HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE macro
* is defined. Its purpose is to check whether there are some undue calls to
* Wrappers::Petsc::Vector::UpdateGhosts() somewhere down the line. It works only in parallel, as
* there are no ghosts ar all in sequential to detect.
*
* Whenever a useless call to Wrappers::Petsc::Vector::UpdateGhosts() is issued, there is a check whether
* the ghosts are actually modified or not. If not, the file and line of calls gets registered here;
* if a subsequent call modify the ghosted values it is removed.
*
*/
class CheckUpdateGhostManager : public Utilities::Singleton<CheckUpdateGhostManager>
{
public:
//! Name of the class (required for some Singleton-related errors).
static const std::string& ClassName();
public:
//! Destructor.
~CheckUpdateGhostManager() = default;
/*!
* \brief Add a new entry.
*/
void UnneededCall(const std::string& file, unsigned int line);
/*!
* \brief Remove if necessary an entry.
*/
void NeededCall(const std::string& file, unsigned int line);
//! Print the content (to call at Model destruction).
void Print() const;
private:
/*!
* \brief Store the list of (file, line) pair in which calls to UpdateGhosts() that do not modify
* the ghosts were called.
*
* An entry might be removed if a subsequent call actually modify the ghosted value.
*/
std::set<std::pair<std::string, unsigned int>>& GetNonCstUnneededCalls() noexcept;
/*!
* \brief Store the list of (file, line) pair in which calls to UpdateGhosts() that do not modify
* the ghosts were called.
*
* An entry might be removed if a subsequent call actually modify the ghosted value.
*/
const std::set<std::pair<std::string, unsigned int>>& GetUnneededCalls() const noexcept;
private:
//! \name Singleton requirements.
///@{
//! Constructor.
CheckUpdateGhostManager() = default;
//! Friendship declaration to Singleton template class (to enable call to constructor).
friend class Utilities::Singleton<CheckUpdateGhostManager>;
///@}
private:
/*!
* \brief Store the list of (file, line) pair in which calls to UpdateGhosts() that do not modify
* the ghosts were called.
*
* An entry might be removed if a subsequent call actually modify the ghosted value.
*/
std::set<std::pair<std::string, unsigned int>> unneeded_calls_;
};
} // namespace Internal
} // namespace Petsc
} // namespace Wrappers
} // namespace HappyHeart
# include "ThirdParty/Wrappers/Petsc/Vector/Private/CheckUpdateGhostManager.hxx"
# endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
#endif // HAPPY_HEART_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_PRIVATE_x_CHECK_UPDATE_GHOST_MANAGER_HPP_
//! \file
//
//
// CheckUpdateGhostManager.hxx
// HappyHeart
//
// Created by Sebastien Gilles on 07/09/16.
// Copyright © 2016 Inria. All rights reserved.
//
#ifndef HAPPY_HEART_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_PRIVATE_x_CHECK_UPDATE_GHOST_MANAGER_HXX_
# define HAPPY_HEART_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_PRIVATE_x_CHECK_UPDATE_GHOST_MANAGER_HXX_
# ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
namespace HappyHeart
{
namespace Wrappers
{
namespace Petsc
{
namespace Internal
{
inline const std::set<std::pair<std::string, unsigned int>>& CheckUpdateGhostManager
::GetUnneededCalls() const noexcept
{
return unneeded_calls_;
}
inline std::set<std::pair<std::string, unsigned int>>& CheckUpdateGhostManager
::GetNonCstUnneededCalls() noexcept
{
return unneeded_calls_;
}
} // namespace Internal
} // namespace Petsc
} // namespace Wrappers
} // namespace HappyHeart
# endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
#endif // HAPPY_HEART_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_PRIVATE_x_CHECK_UPDATE_GHOST_MANAGER_HXX_
......@@ -15,7 +15,8 @@
#include "ThirdParty/Wrappers/Petsc/Viewer.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/Vector.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/AccessVectorContent.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/AccessGhostContent.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/Private/CheckUpdateGhostManager.hpp"
#include "ThirdParty/Wrappers/Petsc/Exceptions/Petsc.hpp"
#include "ThirdParty/Wrappers/Mpi/Mpi.hpp"
......@@ -24,7 +25,6 @@ namespace HappyHeart
{
namespace Wrappers
{
......@@ -342,8 +342,25 @@ namespace HappyHeart
}
#ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
namespace // anonymous
{
std::vector<double> ExtractGhostValues(const Vector& vector,
const char* invoking_file, int invoking_line);
} // namespace anonymous
#endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
void Vector::UpdateGhosts(const char* invoking_file, int invoking_line)
{
#ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
const auto initial_ghost_values = ExtractGhostValues(*this, invoking_file, invoking_line);
#endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
int error_code = VecGhostUpdateBegin(Internal(), INSERT_VALUES, SCATTER_FORWARD);
if (error_code)
throw ExceptionNS::Exception(error_code, "VecGhostUpdateBegin", invoking_file, invoking_line);
......@@ -351,9 +368,71 @@ namespace HappyHeart
error_code = VecGhostUpdateEnd(Internal(), INSERT_VALUES, SCATTER_FORWARD);
if (error_code)
throw ExceptionNS::Exception(error_code, "VecGhostUpdateEnd", invoking_file, invoking_line);
#ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
const auto final_ghost_values = ExtractGhostValues(*this, invoking_file, invoking_line);
// To ignore this in sequential runs!
if (!final_ghost_values.empty())
{
decltype(auto) check_update_ghost_manager = Internal::CheckUpdateGhostManager::GetInstance();
if (initial_ghost_values != final_ghost_values)
check_update_ghost_manager.NeededCall(invoking_file, invoking_line);
else
check_update_ghost_manager.UnneededCall(invoking_file, invoking_line);
}
#endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
}
#ifdef HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
namespace // anonymous
{
decltype(auto) mark = Internal::CheckUpdateGhostManager::CreateOrGetInstance();
std::vector<double> ExtractGhostValues(const Vector& vector,
const char* invoking_file, int invoking_line)
{
# ifdef NDEBUG
std::cout << "HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE should only be defined in debug mode!" << std::endl;
exit(EXIT_FAILURE);
# endif // NDEBUG
Wrappers::Petsc::AccessGhostContent access_ghost_content(vector, invoking_file, invoking_line);
const auto Nitem_on_proc = vector.GetProcessorWiseSize(invoking_file, invoking_line);
const auto& vector_with_ghost = access_ghost_content.GetVectorWithGhost();
Wrappers::Petsc::AccessVectorContent<Utilities::Access::read_only>
vector_with_ghost_content(vector_with_ghost, __FILE__, __LINE__);
const auto size = vector_with_ghost_content.GetSize(invoking_file, invoking_line);
assert(size >= Nitem_on_proc);
std::vector<double> ghost_values;
const auto Nghost = static_cast<std::size_t>(size - Nitem_on_proc);
ghost_values.reserve(Nghost);
for (auto i = Nitem_on_proc; i < size; ++i)
ghost_values.push_back(vector_with_ghost_content.GetValue(i));
assert(ghost_values.size() == Nghost);
return ghost_values;
}
} // namespace anonymous
#endif // HAPPY_HEART_CHECK_UPDATE_GHOSTS_CALL_RELEVANCE
void DisplaySomeValues(std::ostream& stream, const Vector& vector, PetscInt firstIndex, PetscInt lastIndex,
int rankProc, const char* invoking_file, int invoking_line)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment