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

Build succeed and make failed for hpx:cout #3567

Closed
Jiazheng-Yuan opened this issue Nov 27, 2018 · 2 comments
Closed

Build succeed and make failed for hpx:cout #3567

Jiazheng-Yuan opened this issue Nov 27, 2018 · 2 comments

Comments

@Jiazheng-Yuan
Copy link

Jiazheng-Yuan commented Nov 27, 2018

Expected Behavior

... Please describe the behavior you would have expected.
make would succeed

Actual Behavior

failed
... Please describe the behavior you actually observed.

Scanning dependencies of target example
[ 50%] Building CXX object CMakeFiles/example.dir/main.cpp.o
[100%] Linking CXX executable example
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `final_task(hpx::lcos::future<hpx::util::tuple<hpx::lcos::future<double>, hpx::lcos::future<void> > >)':
main.cpp:(.text+0xb7): undefined reference to `hpx::cout'
/usr/bin/ld: main.cpp:(.text+0xc3): undefined reference to `hpx::iostreams::endl'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `main':
main.cpp:(.text+0x322): undefined reference to `hpx::cout'
/usr/bin/ld: main.cpp:(.text+0x32e): undefined reference to `hpx::iostreams::endl'
/usr/bin/ld: main.cpp:(.text+0x344): undefined reference to `hpx::cout'
/usr/bin/ld: main.cpp:(.text+0x37a): undefined reference to `hpx::iostreams::endl'
/usr/bin/ld: main.cpp:(.text+0x4cb): undefined reference to `hpx::cout'
/usr/bin/ld: main.cpp:(.text+0x501): undefined reference to `hpx::iostreams::endl'
/usr/bin/ld: main.cpp:(.text+0x6d6): undefined reference to `hpx::cout'
/usr/bin/ld: main.cpp:(.text+0x6e2): undefined reference to `hpx::iostreams::endl'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `void hpx::lcos::packaged_action<hpx::iostreams::server::output_stream::write_sync_action, void, false>::do_apply<unsigned int, unsigned long, hpx::iostreams::detail::buffer&>(hpx::naming::address&&, hpx::naming::id_type const&, hpx::threads::thread_priority, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&)':
main.cpp:(.text._ZN3hpx4lcos15packaged_actionINS_9iostreams6server13output_stream17write_sync_actionEvLb0EE8do_applyIJjmRNS2_6detail6bufferEEEEvONS_6naming7addressERKNSB_7id_typeENS_7threads15thread_priorityEDpOT_[_ZN3hpx4lcos15packaged_actionINS_9iostreams6server13output_stream17write_sync_actionEvLb0EE8do_applyIJjmRNS2_6detail6bufferEEEEvONS_6naming7addressERKNSB_7id_typeENS_7threads15thread_priorityEDpOT_]+0xd6): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `bool hpx::apply_p_cb<hpx::iostreams::server::output_stream::write_sync_action, hpx::actions::typed_continuation<void, hpx::util::unused_type>, hpx::util::detail::bound_front<void (*)(boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> >, boost::system::error_code const&, hpx::parcelset::parcel const&), boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> > >, unsigned int, unsigned long, hpx::iostreams::detail::buffer&>(hpx::actions::typed_continuation<void, hpx::util::unused_type>&&, hpx::naming::address&&, hpx::naming::id_type const&, hpx::threads::thread_priority, hpx::util::detail::bound_front<void (*)(boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> >, boost::system::error_code const&, hpx::parcelset::parcel const&), boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> > >&&, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&)':
main.cpp:(.text._ZN3hpx10apply_p_cbINS_9iostreams6server13output_stream17write_sync_actionENS_7actions18typed_continuationIvNS_4util11unused_typeEEENS7_6detail11bound_frontIPFvN5boost13intrusive_ptrINS_4lcos6detail12promise_dataIvEEEERKNSC_6system10error_codeERKNS_9parcelset6parcelEEJSI_EEEJjmRNS1_6detail6bufferEEEEbOT0_ONS_6naming7addressERKNSZ_7id_typeENS_7threads15thread_priorityEOT1_DpOT2_[_ZN3hpx10apply_p_cbINS_9iostreams6server13output_stream17write_sync_actionENS_7actions18typed_continuationIvNS_4util11unused_typeEEENS7_6detail11bound_frontIPFvN5boost13intrusive_ptrINS_4lcos6detail12promise_dataIvEEEERKNSC_6system10error_codeERKNS_9parcelset6parcelEEJSI_EEEJjmRNS1_6detail6bufferEEEEbOT0_ONS_6naming7addressERKNSZ_7id_typeENS_7threads15thread_priorityEOT1_DpOT2_]+0xb0): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::basic_action_impl<void (hpx::iostreams::server::output_stream::*)(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&), void (hpx::iostreams::server::output_stream::*)(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&), &hpx::iostreams::server::output_stream::write_sync, hpx::iostreams::server::output_stream::write_sync_action>::get_action_name[abi:cxx11](unsigned long)':
main.cpp:(.text._ZN3hpx7actions17basic_action_implIMNS_9iostreams6server13output_streamEFvjmRKNS2_6detail6bufferEESA_XadL_ZNS4_10write_syncEjmS8_EENS4_17write_sync_actionEE15get_action_nameB5cxx11Em[_ZN3hpx7actions17basic_action_implIMNS_9iostreams6server13output_streamEFvjmRKNS2_6detail6bufferEESA_XadL_ZNS4_10write_syncEjmS8_EENS4_17write_sync_actionEE15get_action_nameB5cxx11Em]+0x5a): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `std::enable_if<hpx::traits::is_continuation<hpx::actions::typed_continuation<void, hpx::util::unused_type>, void>::value, bool>::type hpx::detail::apply_cb_impl<hpx::iostreams::server::output_stream::write_sync_action, hpx::actions::typed_continuation<void, hpx::util::unused_type>, hpx::util::detail::bound_front<void (*)(boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> >, boost::system::error_code const&, hpx::parcelset::parcel const&), boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> > >, unsigned int, unsigned long, hpx::iostreams::detail::buffer&>(hpx::actions::typed_continuation<void, hpx::util::unused_type>&&, hpx::naming::id_type const&, hpx::threads::thread_priority, hpx::util::detail::bound_front<void (*)(boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> >, boost::system::error_code const&, hpx::parcelset::parcel const&), boost::intrusive_ptr<hpx::lcos::detail::promise_data<void> > >&&, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&)':
main.cpp:(.text._ZN3hpx6detail13apply_cb_implINS_9iostreams6server13output_stream17write_sync_actionENS_7actions18typed_continuationIvNS_4util11unused_typeEEENS8_6detail11bound_frontIPFvN5boost13intrusive_ptrINS_4lcos6detail12promise_dataIvEEEERKNSD_6system10error_codeERKNS_9parcelset6parcelEEJSJ_EEEJjmRNS2_6detail6bufferEEEENSt9enable_ifIXsrNS_6traits15is_continuationIT0_vEE5valueEbE4typeEOS11_RKNS_6naming7id_typeENS_7threads15thread_priorityEOT1_DpOT2_[_ZN3hpx6detail13apply_cb_implINS_9iostreams6server13output_stream17write_sync_actionENS_7actions18typed_continuationIvNS_4util11unused_typeEEENS8_6detail11bound_frontIPFvN5boost13intrusive_ptrINS_4lcos6detail12promise_dataIvEEEERKNSD_6system10error_codeERKNS_9parcelset6parcelEEJSJ_EEEJjmRNS2_6detail6bufferEEEENSt9enable_ifIXsrNS_6traits15is_continuationIT0_vEE5valueEbE4typeEOS11_RKNS_6naming7id_typeENS_7threads15thread_priorityEOT1_DpOT2_]+0xb0): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `int hpx::components::get_component_type<hpx::iostreams::server::output_stream>()':
main.cpp:(.text._ZN3hpx10components18get_component_typeINS_9iostreams6server13output_streamEEEiv[_ZN3hpx10components18get_component_typeINS_9iostreams6server13output_streamEEEiv]+0x5): undefined reference to `hpx::traits::component_type_database<hpx::iostreams::server::output_stream, void>::get()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `std::enable_if<!hpx::traits::is_future<void>::value, void>::type hpx::actions::basic_action_impl<void (hpx::iostreams::server::output_stream::*)(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&), void (hpx::iostreams::server::output_stream::*)(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&), &hpx::iostreams::server::output_stream::write_sync, hpx::iostreams::server::output_stream::write_sync_action>::invoke_helper<void, unsigned int, unsigned long, hpx::iostreams::detail::buffer&>(hpx::actions::detail::tag<void>, unsigned long, int, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&)':
main.cpp:(.text._ZN3hpx7actions17basic_action_implIMNS_9iostreams6server13output_streamEFvjmRKNS2_6detail6bufferEESA_XadL_ZNS4_10write_syncEjmS8_EENS4_17write_sync_actionEE13invoke_helperIvJjmRS6_EEENSt9enable_ifIXntsrNS_6traits9is_futureIT_EE5valueESI_E4typeENS0_6detail3tagISI_EEmiDpOT0_[_ZN3hpx7actions17basic_action_implIMNS_9iostreams6server13output_streamEFvjmRKNS2_6detail6bufferEESA_XadL_ZNS4_10write_syncEjmS8_EENS4_17write_sync_actionEE13invoke_helperIvJjmRS6_EEENSt9enable_ifIXntsrNS_6traits9is_futureIT_EE5valueESI_E4typeENS0_6detail3tagISI_EEmiDpOT0_]+0x6c): undefined reference to `hpx::iostreams::server::output_stream::write_sync(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&)'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::transfer_continuation_action<hpx::iostreams::server::output_stream::write_sync_action>::transfer_continuation_action<hpx::threads::thread_priority&, unsigned int, unsigned long, hpx::iostreams::detail::buffer&>(hpx::actions::typed_continuation<void, hpx::util::unused_type>&&, hpx::threads::thread_priority&, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&)':
main.cpp:(.text._ZN3hpx7actions28transfer_continuation_actionINS_9iostreams6server13output_stream17write_sync_actionEEC2IJRNS_7threads15thread_priorityEjmRNS2_6detail6bufferEEEEONS0_18typed_continuationIvNS_4util11unused_typeEEEDpOT_[_ZN3hpx7actions28transfer_continuation_actionINS_9iostreams6server13output_stream17write_sync_actionEEC5IJRNS_7threads15thread_priorityEjmRNS2_6detail6bufferEEEEONS0_18typed_continuationIvNS_4util11unused_typeEEEDpOT_]+0x7c): undefined reference to `vtable for hpx::actions::transfer_continuation_action<hpx::iostreams::server::output_stream::write_sync_action>'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::transfer_continuation_action<hpx::iostreams::server::output_stream::write_sync_action>::transfer_continuation_action<hpx::threads::thread_priority, unsigned int, unsigned long, hpx::iostreams::detail::buffer>(hpx::actions::typed_continuation<void, hpx::util::unused_type>&&, hpx::threads::thread_priority&&, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&&)':
main.cpp:(.text._ZN3hpx7actions28transfer_continuation_actionINS_9iostreams6server13output_stream17write_sync_actionEEC2IJNS_7threads15thread_priorityEjmNS2_6detail6bufferEEEEONS0_18typed_continuationIvNS_4util11unused_typeEEEDpOT_[_ZN3hpx7actions28transfer_continuation_actionINS_9iostreams6server13output_stream17write_sync_actionEEC5IJNS_7threads15thread_priorityEjmNS2_6detail6bufferEEEEONS0_18typed_continuationIvNS_4util11unused_typeEEEDpOT_]+0x7c): undefined reference to `vtable for hpx::actions::transfer_continuation_action<hpx::iostreams::server::output_stream::write_sync_action>'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::detail::register_action<hpx::iostreams::server::output_stream::write_sync_action>::register_action()':
main.cpp:(.text._ZN3hpx7actions6detail15register_actionINS_9iostreams6server13output_stream17write_sync_actionEEC2Ev[_ZN3hpx7actions6detail15register_actionINS_9iostreams6server13output_stream17write_sync_actionEEC5Ev]+0x22): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::transfer_continuation_action<hpx::iostreams::server::output_stream::write_sync_action>::transfer_continuation_action()':
main.cpp:(.text._ZN3hpx7actions28transfer_continuation_actionINS_9iostreams6server13output_stream17write_sync_actionEEC2Ev[_ZN3hpx7actions28transfer_continuation_actionINS_9iostreams6server13output_stream17write_sync_actionEEC5Ev]+0x1c): undefined reference to `vtable for hpx::actions::transfer_continuation_action<hpx::iostreams::server::output_stream::write_sync_action>'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::transfer_action<hpx::iostreams::server::output_stream::write_sync_action>::transfer_action()':
main.cpp:(.text._ZN3hpx7actions15transfer_actionINS_9iostreams6server13output_stream17write_sync_actionEEC2Ev[_ZN3hpx7actions15transfer_actionINS_9iostreams6server13output_stream17write_sync_actionEEC5Ev]+0x1b): undefined reference to `vtable for hpx::actions::transfer_action<hpx::iostreams::server::output_stream::write_sync_action>'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `std::enable_if<!hpx::traits::is_future<void>::value, void>::type hpx::actions::basic_action_impl<void (hpx::iostreams::server::output_stream::*)(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&), void (hpx::iostreams::server::output_stream::*)(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&), &hpx::iostreams::server::output_stream::write_sync, hpx::iostreams::server::output_stream::write_sync_action>::invoke_helper<void, unsigned int, unsigned long, hpx::iostreams::detail::buffer>(hpx::actions::detail::tag<void>, unsigned long, int, unsigned int&&, unsigned long&&, hpx::iostreams::detail::buffer&&)':
main.cpp:(.text._ZN3hpx7actions17basic_action_implIMNS_9iostreams6server13output_streamEFvjmRKNS2_6detail6bufferEESA_XadL_ZNS4_10write_syncEjmS8_EENS4_17write_sync_actionEE13invoke_helperIvJjmS6_EEENSt9enable_ifIXntsrNS_6traits9is_futureIT_EE5valueESH_E4typeENS0_6detail3tagISH_EEmiDpOT0_[_ZN3hpx7actions17basic_action_implIMNS_9iostreams6server13output_streamEFvjmRKNS2_6detail6bufferEESA_XadL_ZNS4_10write_syncEjmS8_EENS4_17write_sync_actionEE13invoke_helperIvJjmS6_EEENSt9enable_ifIXntsrNS_6traits9is_futureIT_EE5valueESH_E4typeENS0_6detail3tagISH_EEmiDpOT0_]+0x6c): undefined reference to `hpx::iostreams::server::output_stream::write_sync(unsigned int, unsigned long, hpx::iostreams::detail::buffer const&)'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `hpx::actions::transfer_base_action<hpx::iostreams::server::output_stream::write_sync_action>::get_action_name() const':
main.cpp:(.text._ZNK3hpx7actions20transfer_base_actionINS_9iostreams6server13output_stream17write_sync_actionEE15get_action_nameEv[_ZNK3hpx7actions20transfer_base_actionINS_9iostreams6server13output_stream17write_sync_actionEE15get_action_nameEv]+0xd): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
/usr/bin/ld: CMakeFiles/example.dir/main.cpp.o: in function `unsigned int hpx::actions::detail::get_action_id<hpx::iostreams::server::output_stream::write_sync_action>()':
main.cpp:(.text._ZN3hpx7actions6detail13get_action_idINS_9iostreams6server13output_stream17write_sync_actionEEEjv[_ZN3hpx7actions6detail13get_action_idINS_9iostreams6server13output_stream17write_sync_actionEEEjv]+0x33): undefined reference to `char const* hpx::actions::detail::get_action_name<hpx::iostreams::server::output_stream::write_sync_action>()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/example.dir/build.make:103: example] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/example.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Steps to Reproduce the Problem

... Please be as specific as possible while describing how to reproduce your problem.
This is what I have in my CMakeList.txt, I am trying to use pybind11 with hpx

cmake_minimum_required(VERSION 3.0)
project(example CXX)
find_package(HPX REQUIRED)
find_package(pybind11 REQUIRED)  
add_executable(example main.cpp)
target_link_libraries(example hpx)
hpx_setup_target(example)
target_link_libraries(example pybind11::embed)

instruction used

cmake -DPYTHON_EXECUTABLE=$python3_location -Dpybind11_DIR=$pybind_location -DHPX_DIR=$hpx_install_location/lib/cmake/HPX -DCMAKE_PREFIX_PATH=$hpx_install_location ..

C++ code used(example from documentation)

#include <hpx/hpx_main.hpp>
#include <hpx/include/iostreams.hpp>
#include <hpx/include/lcos.hpp>
#include <hpx/include/parallel_generate.hpp>
#include <hpx/include/parallel_sort.hpp>
#include<pybind11/embed.h>

#include <random>
#include <vector>

void final_task(hpx::future<hpx::util::tuple<hpx::future<double>, hpx::future<void>>>)
{
    hpx::cout << "in final_task" << hpx::endl;
}

int main(int, char**)
{
    // A function can be launched asynchronously. The program will not block
    // here until the result is available.
    hpx::future<int> f = hpx::async([]() { return 42; });
    hpx::cout << "Just launched a task!" << hpx::endl;

    // Use get to retrieve the value from the future. This will block this task
    // until the future is ready, but the HPX runtime will schedule other tasks
    // if there are tasks available.
    hpx::cout << "f contains " << f.get() << hpx::endl;

    // Let's launch another task.
    hpx::future<double> g = hpx::async([]() { return 3.14; });

    // Tasks can be chained using the then method. The continuation takes the
    // future as an argument.
    hpx::future<double> result = g.then([](hpx::future<double>&& gg)
        {
            // This function will be called once g is ready. gg is g moved
            // into the continuation.
            return gg.get() * 42.0 * 42.0;
        });

    // You can check if a future is ready with the is_ready method.
    hpx::cout << "Result is ready? " << result.is_ready() << hpx::endl;

    // You can launch other work in the meantime. Let's sort a vector.
    std::vector<int> v(1000000);

    // We fill the vector synchronously and sequentially.
    hpx::parallel::generate(hpx::parallel::execution::seq,
                  std::begin(v), std::end(v), &std::rand);

    // We can launch the sort in parallel and asynchronously.
    hpx::future<void> done_sorting =
        hpx::parallel::sort(
            hpx::parallel::execution::par( // In parallel.
                hpx::parallel::execution::task), // Asynchronously.
            std::begin(v),
            std::end(v));

    // We launch the final task when the vector has been sorted and result is
    // ready using when_all.
    auto all = hpx::when_all(result, done_sorting).then(&final_task);

    // We can wait for all to be ready.
    all.wait();

    // all must be ready at this point because we waited for it to be ready.
    hpx::cout <<
        (all.is_ready() ? "all is ready!" : "all is not ready...") << hpx::endl;

    return hpx::finalize();
}

output for build

-- The CXX compiler identification is GNU 8.2.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The C compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- WARNING: HPX will perform poorly without tcmalloc or jemalloc. See docs for more info.
-- Using system allocator.
-- Found PythonInterp: /home/jyuan18/shared/jiazheng/venv3.7/bin/python3 (found version "3.7.1") 
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython3.7m.so
-- Performing Test HAS_CPP14_FLAG
-- Performing Test HAS_CPP14_FLAG - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jyuan18/shared/jiazheng/test_dir/hpx_build/deeper

Build would succeed, but make would fail. If i turn off all the iostream it would run normally. I am
new to hpx, don't really know what happened. I was trying to use hpx with pybind11.

Specifications

... Please describe your environment

  • HPX Version: hpx_1.2.0
  • Platform (compiler, OS):g++ (Debian 8.2.0-9) 8.2.0
@msimberg
Copy link
Contributor

Thanks for the report. hpx::cout is provided by a separate library/component and has to be linked to explicitly. To do so you can change your hpx_setup_target(example) to hpx_setup_target(example COMPONENT_DEPENDENCIES iostreams) (docs here).

Like you said using std::cout works as well, but I'd still recommend you use hpx::cout for two reasons. First, hpx::cout will do the actual writing to std::cout on a separate thread which means that hpx::cout will never block our scheduler. Second, hpx::cout will redirect output from multiple localities/nodes to the main locality.

@Jiazheng-Yuan
Copy link
Author

Thanks.It works well now!

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

No branches or pull requests

3 participants