From: Matthias Maier Date: Thu, 5 Mar 2020 01:29:30 +0000 (-0600) Subject: remove asynchronous IO mechanism X-Git-Tag: v9.2.0-rc1~443^2~3 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7980483d1654923c44f67491699b82e6b5ce4e51;p=dealii.git remove asynchronous IO mechanism --- diff --git a/examples/step-69/step-69.cc b/examples/step-69/step-69.cc index 2c102e99d3..6f04d0f9e8 100644 --- a/examples/step-69/step-69.cc +++ b/examples/step-69/step-69.cc @@ -499,9 +499,6 @@ namespace Step69 InitialValues initial_values; TimeStepping time_stepping; SchlierenPostprocessor schlieren_postprocessor; - - std::thread output_thread; - vector_type output_vector; }; // @sect3{Implementation} @@ -2654,12 +2651,6 @@ namespace Step69 } } - // We wait for any remaining background output thread to finish before - // printing a summary and exiting. - - if (output_thread.joinable()) - output_thread.join(); - computing_timer.print_summary(); pcout << timer_output.str() << std::endl; } @@ -2708,19 +2699,6 @@ namespace Step69 } // @sect5{Output and checkpointing} - // - // Writing out the final vtk files is a quite IO intensive task that can - // stall the main loop quite a bit. In order to avoid this we use an asynchronous - // IO strategy by creating a background thread that will perform IO - // while the main loop is allowed to continue. In order for this to work - // we have to be mindful of two things: - // - Before running the output_worker thread, we have to create - // a copy of the state vector U. We store it in the - // vector output_vector. - // - We have to avoid any MPI communication in the background thread, - // otherwise the program might deadlock. This implies that we have to - // run the postprocessing outside of the worker thread. template void MainLoop::output(const typename MainLoop::vector_type &U, @@ -2732,98 +2710,57 @@ namespace Step69 pcout << "MainLoop::output(t = " << t << ", checkpoint = " << checkpoint << ")" << std::endl; - // We check whether the output thread is still running. If so, we have - // to wait to for it to finish because we would otherwise overwrite - // output_vector and rerun the - // schlieren_postprocessor before the output of the - // previous output cycle has been fully written back to disk. + TimerOutput::Scope scope(computing_timer, "main_loop - output"); - if (output_thread.joinable()) + if (checkpoint) { - TimerOutput::Scope timer(computing_timer, "main_loop - stalled output"); - output_thread.join(); - } + // We checkpoint the current state by doing the precise inverse + // operation to what we discussed for the resume + // logic: - constexpr auto problem_dimension = - ProblemDescription::problem_dimension; + const unsigned int i = + discretization.triangulation.locally_owned_subdomain(); + std::string name = base_name + "-checkpoint-" + + Utilities::int_to_string(i, 4) + ".archive"; - // At this point we make a copy of the state vector and run the - // schlieren postprocessor. + std::ofstream file(name, std::ios::binary | std::ios::trunc); - for (unsigned int i = 0; i < problem_dimension; ++i) - { - output_vector[i] = U[i]; - output_vector[i].update_ghost_values(); + boost::archive::binary_oarchive oa(file); + oa << t << cycle; + for (const auto &it1 : U) + for (const auto &it2 : it1) + oa << it2; } - schlieren_postprocessor.compute_schlieren(output_vector); + schlieren_postprocessor.compute_schlieren(U); - // Next we create a lambda function for the background thread. We capture - // the this pointer as well as most of the arguments of - // the output function by value so that we have access to them inside - // the lambda function. + // The actual output code is standard. We create a (local) DataOut + // instance, attach all data vectors we want to output and finally + // call to DataOut::write_vtu_with_pvtu_record - const auto output_worker = [this, name, t, cycle, checkpoint]() { - if (checkpoint) - { - // We checkpoint the current state by doing the precise inverse - // operation to what we discussed for the resume - // logic: - - const unsigned int i = - discretization.triangulation.locally_owned_subdomain(); - std::string name = base_name + "-checkpoint-" + - Utilities::int_to_string(i, 4) + ".archive"; - - std::ofstream file(name, std::ios::binary | std::ios::trunc); - - boost::archive::binary_oarchive oa(file); - oa << t << cycle; - for (const auto &it1 : output_vector) - for (const auto &it2 : it1) - oa << it2; - } - - // The actual output code is standard. We create a (local) DataOut - // instance, attach all data vectors we want to output and finally - // call to DataOut::write_vtu_with_pvtu_record - - DataOut data_out; - data_out.attach_dof_handler(offline_data.dof_handler); - - constexpr auto problem_dimension = - ProblemDescription::problem_dimension; - const auto &component_names = ProblemDescription::component_names; + DataOut data_out; + data_out.attach_dof_handler(offline_data.dof_handler); - for (unsigned int i = 0; i < problem_dimension; ++i) - data_out.add_data_vector(output_vector[i], component_names[i]); - - data_out.add_data_vector(schlieren_postprocessor.schlieren, - "schlieren_plot"); + constexpr auto problem_dimension = + ProblemDescription::problem_dimension; + const auto &component_names = ProblemDescription::component_names; - data_out.build_patches(discretization.mapping, - discretization.finite_element.degree - 1); + for (unsigned int i = 0; i < problem_dimension; ++i) + data_out.add_data_vector(U[i], component_names[i]); - DataOutBase::VtkFlags flags(t, - cycle, - true, - DataOutBase::VtkFlags::best_speed); - data_out.set_flags(flags); + data_out.add_data_vector(schlieren_postprocessor.schlieren, + "schlieren_plot"); - data_out.write_vtu_with_pvtu_record("", name, cycle, mpi_communicator, 6); - }; + data_out.build_patches(discretization.mapping, + discretization.finite_element.degree - 1); - // We launch the thread by creating a - // std::thread - // object from the lambda function and moving it into the - // output_thread thread object. At this point we can - // return from the output() function and resume with the - // time stepping in the main loop - the thread will run in the - // background. + DataOutBase::VtkFlags flags(t, + cycle, + true, + DataOutBase::VtkFlags::best_speed); + data_out.set_flags(flags); - output_thread = std::move(std::thread(output_worker)); + data_out.write_vtu_with_pvtu_record("", name, cycle, mpi_communicator, 6); } } // namespace Step69