Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: add MPI_Finalize in QUIT function #5505

Closed
wants to merge 8 commits into from

Conversation

kirk0830
Copy link
Collaborator

Reminder

  • Have you linked an issue with this pull request?
  • Have you added adequate unit tests and/or case tests for your pull request?
  • Have you noticed possible changes of behavior below or in the linked issue?
  • Have you explained the changes of codes in core modules of ESolver, HSolver, ElecState, Hamilt, Operator or Psi? (ignore if not applicable)

Linked Issue

Fix #5486

Unit Tests and/or Case Tests for my changes

  • A unit test is added for each new feature or bug fix.

What's changed?

  • Example: My changes might affect the performance of the application under certain conditions, and I have tested the impact on various scenarios...

Any changes of core modules? (ignore if not applicable)

  • Example: I have added a new virtual function in the esolver base class in order to ...

@kirk0830
Copy link
Collaborator Author

Those unittests failed in a weird way. I need more time to understand what happened.
For example the CMakeLists of unittest of Charge_Mixing removes the definition of macro __MPI, so the change made in function QUIT should have no effect at all, but this is not how the program works now.

PS. What I have done in function QUIT is adding lines:

#ifdef __MPI
    MPI_Finalize();
#endif

Copy link
Member

@caic99 caic99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Your comments in the codes would be more helpful if they are submitted as new issues.

@kirk0830
Copy link
Collaborator Author

kirk0830 commented Nov 18, 2024

@jinzx10 helps me find it is the math_libs will link with MPI. The line remove_definitions(-D__MPI) in CMakeLists.txt of unittest does not work as what the programmer expected.
The line I add, MPI_Finalize(), will still be called but without MPI_Init().
I need some time to solve this.

@mohanchen mohanchen added the Refactor Refactor ABACUS codes label Nov 19, 2024
@kirk0830
Copy link
Collaborator Author

I met severe problems related to EXPECT_EXIT/EXPECT_DEATH. This kind of test works in the following way, according to the annotation of gtest-death-test.h:
gtest-death-test
. It is only when the test is run purely single-thread, will the test be thread-safe. However, Googletest will pop warning like there is more than 1 threads active, and the test will time out.

Due to the complexity of ABACUS unittest now, I cannot continue with this PR temporarily, so I close it for now.

@kirk0830 kirk0830 closed this Nov 19, 2024
@kirk0830
Copy link
Collaborator Author

here I paste a minimal work example:

#ifdef __MPI
#include <mpi.h>
#endif
#include <iostream>
#include <gtest/gtest.h>

void foo(const int signal)
{
    if (signal == 0)
    {
        std::cout << "Normal exit" << std::endl;
    }
    else
    {
        std::cout << "Abnormal exit with signal " << signal << std::endl;
        #ifdef __MPI // MPI_Finalize() is called in the case of abnormal exit?
        // MPI_Finalize();
        #endif
        exit(signal);
    }
}

TEST(hw, test1)
{
    // capture stdout
    testing::internal::CaptureStdout();
    foo(0);
    const std::string out = testing::internal::GetCapturedStdout();
    EXPECT_EQ(out, "Normal exit\n");

    int irank = 0;
    #ifdef __MPI
    MPI_Comm_rank(MPI_COMM_WORLD, &irank);
    #endif
    if (irank == 0)
    {
        std::cout << "Captured stdout: " << out << std::endl;
    }
}

TEST(hw, test2)
{
    testing::internal::CaptureStdout();
    EXPECT_EXIT(foo(1), ::testing::ExitedWithCode(1), "");
    const std::string out = testing::internal::GetCapturedStdout();
    EXPECT_EQ(out, "Abnormal exit with signal 1\n");

    int irank = 0;
    #ifdef __MPI
    MPI_Comm_rank(MPI_COMM_WORLD, &irank);
    #endif
    if (irank == 0)
    {
        std::cout << "Captured stdout: " << out << std::endl;
    }
}

int main(int argc, char **argv)
{
    #ifdef __MPI
    MPI_Init(&argc, &argv);
    #endif
    ::testing::InitGoogleTest(&argc, argv);
    // ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    const int result = RUN_ALL_TESTS();
    #ifdef __MPI
    MPI_Finalize();
    #endif
    return result;
}

with following CMakeLists.txt

project(whatswrong) # this is merely soft-required, but meaningless pratically
cmake_minimum_required(VERSION 3.22) # this is merely soft-required, but meaningless pratically
add_executable(test hw_mpi.cpp)
target_link_libraries(test gtest gtest_main)
# find mpi
find_package(MPI REQUIRED)
include_directories(${MPI_INCLUDE_PATH})
add_test(NAME test COMMAND test)

# if the WITH_MPI flag is set, then define the __MPI macro
if(WITH_MPI)
    target_compile_definitions(test PRIVATE __MPI)
    target_link_libraries(test ${MPI_LIBRARIES})
endif()

@kirk0830
Copy link
Collaborator Author

the unittest of (for instance) the charge_mixing failed because:

  1. The MPI macro definition is not removed absolutely, it is still in the state of being defined in those included libs such as math_libs and base. Therefore no matter whether there is remove_definition(-D__MPI) in CMakeLists.txt of the unittest, there will still be mpi related code linked.
  2. However, because the MPI_Init() is never called in unittest (the unittest of charge_mixing even does not have a main function!), so the call of MPI_Finalize is illegal (because MPI_Init() and MPI_Finalize() calls are not well-paired).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Refactor Refactor ABACUS codes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: function WARNING_QUIT does not finalize the MPI processes correctly
3 participants