diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a113fc6a5..1cd8697119 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,9 @@ if (TTG_ENABLE_ASAN) add_link_options(-fsanitize=address) endif (TTG_ENABLE_ASAN) +# someone thought it was a brilliant idea to automatically enable thread-parallel BLAS +set(use_openmp OFF) + set(TTG_HIP_PLATFORM "__HIP_PLATFORM_AMD__" CACHE STRING "Which platform to use when compiling HIP-related code (default: __HIP_PLATFORM_AMD__)") ########################## #### prerequisites diff --git a/cmake/modules/ExternalDependenciesVersions.cmake b/cmake/modules/ExternalDependenciesVersions.cmake index bf1a492d48..fd67f09a45 100644 --- a/cmake/modules/ExternalDependenciesVersions.cmake +++ b/cmake/modules/ExternalDependenciesVersions.cmake @@ -4,11 +4,11 @@ set(TTG_TRACKED_VG_CMAKE_KIT_TAG 256d9462bb765787f5acb69be154b26d6efba8b6) # provides FindOrFetchLinalgPP and "real" FindOrFetchBoost set(TTG_TRACKED_CATCH2_VERSION 3.5.0) -set(TTG_TRACKED_MADNESS_TAG a50e8d440fc2a1718a1ba0140af6866f49813d14) +set(TTG_TRACKED_MADNESS_TAG fe58bba88857ceeb530a1ef3bdf8744516d80452) set(TTG_TRACKED_PARSEC_TAG parsec-for-ttg) -set(TTG_TRACKED_UMPIRE_CXX_ALLOCATOR_TAG a48ad360e20b9733263768b54aa24afe5894faa4) -set(TTG_TRACKED_BTAS_TAG c25b0a11d2a76190bfb13fa72f9e9dc3e57c3c2f) -set(TTG_TRACKED_TILEDARRAY_TAG 42e0d65df9400469d29ebeb929b045be1caaf3d6) +set(TTG_TRACKED_UMPIRE_CXX_ALLOCATOR_TAG 1ba7f5f0aa99438826dd1c6bc1cd396080b9d608) +set(TTG_TRACKED_BTAS_TAG 74ee8a27386c746b36f0455cd5a0e3c33bd5f4d2) +set(TTG_TRACKED_TILEDARRAY_TAG c4a8927845e0c4503ecacf85ce8e73243ab48a62) # need Boost.CallableTraits (header only, part of Boost 1.66 released in Dec 2017) for wrap.h to work # BUT if will be building examples, inherit the oldest version from the pickiest Boost consumer (TA and/or BSPMM) diff --git a/ttg/CMakeLists.txt b/ttg/CMakeLists.txt index fb29615478..d33ab7eefc 100644 --- a/ttg/CMakeLists.txt +++ b/ttg/CMakeLists.txt @@ -238,7 +238,7 @@ if (TARGET MADworld) # N.B. ttg-mad can use MADNESS serialization only add_ttg_library(ttg-mad "${ttg-mad-headers}" PUBLIC_HEADER "${ttg-mad-headers}" - LINK_LIBRARIES "ttg;MADworld;ttg-serialization-madness" + LINK_LIBRARIES "ttg;MADworld;MADmisc;ttg-serialization-madness" COMPILE_DEFINITIONS "WORLD_INSTANTIATE_STATIC_TEMPLATES=1" COMPILE_DEFINITIONS TTG_USE_MADNESS=1) endif(TARGET MADworld) diff --git a/ttg/ttg/device/task.h b/ttg/ttg/device/task.h index f71935ddac..4ba85b9f43 100644 --- a/ttg/ttg/device/task.h +++ b/ttg/ttg/device/task.h @@ -47,6 +47,13 @@ namespace ttg::device { } } // namespace detail + /** + * A collection of input buffer objects to be used in a device task. + * + * TODO: + * - Filter out empty buffers. They can cause problems if empty flows appear between non-empty flows. + * - Filter out or error out on duplicated buffers. + */ struct Input { private: std::vector m_data; @@ -328,7 +335,7 @@ namespace ttg::device { template struct broadcast_keylist_trait { - using type = T; + using key_type = T; }; /* overload for iterable types that extracts the type of the first element */ @@ -500,41 +507,62 @@ namespace ttg::device { valueT &&value, std::tuple...> &t) { ttg::detail::value_copy_handler copy_handler; - return detail::send_t{ - detail::broadcast_coro(std::forward(keylist), - copy_handler(std::forward(value)), - t, std::move(copy_handler))}; + if constexpr (ttg::meta::is_tuple_v) { + return detail::send_t{ + detail::broadcast_coro(std::forward(keylist), + copy_handler(std::forward(value)), + t, std::move(copy_handler))}; + } else { + return detail::send_t{ + detail::broadcast_coro(std::tie(keylist), + copy_handler(std::forward(value)), + t, std::move(copy_handler))}; + } } /* overload with implicit terminals and keylist passed by const reference */ - template - inline detail::send_t broadcast(rangeT &&keylist, valueT &&value) { + inline detail::send_t broadcast(RangesT &&keylist, valueT &&value) { ttg::detail::value_copy_handler copy_handler; - return detail::send_t{detail::broadcast_coro(std::tie(keylist), - copy_handler(std::forward(value)), - std::move(copy_handler))}; + if constexpr (ttg::meta::is_tuple_v) { + return detail::send_t{detail::broadcast_coro(std::forward(keylist), + copy_handler(std::forward(value)), + std::move(copy_handler))}; + } else if constexpr(std::is_rvalue_reference_v) { + return detail::send_t{detail::broadcast_coro(std::make_tuple(std::forward(keylist)), + copy_handler(std::forward(value)), + std::move(copy_handler))}; + } else { + return detail::send_t{detail::broadcast_coro(std::tie(keylist), + copy_handler(std::forward(value)), + std::move(copy_handler))}; + } } /* overload with explicit terminals and keylist passed by const reference */ - template [[nodiscard]] - inline detail::send_t broadcastk(rangeT &&keylist, + inline detail::send_t broadcastk(RangesT &&keylist, std::tuple...> &t) { ttg::detail::value_copy_handler copy_handler; - return detail::send_t{ - detail::broadcastk_coro(std::forward(keylist), t)}; + if constexpr (ttg::meta::is_tuple_v) { + return detail::send_t{detail::broadcastk_coro(std::forward(keylist), t)}; + } else { + return detail::send_t{ + detail::broadcastk_coro(std::tie(keylist), t)}; + } } /* overload with implicit terminals and keylist passed by const reference */ - template - inline detail::send_t broadcastk(rangeT &&keylist) { - if constexpr (std::is_rvalue_reference_v) { - return detail::send_t{detail::broadcastk_coro(std::forward(keylist))}; + inline detail::send_t broadcastk(RangesT &&keylist) { + if constexpr (ttg::meta::is_tuple_v) { + return detail::send_t{detail::broadcastk_coro(std::forward(keylist))}; } else { - return detail::send_t{detail::broadcastk_coro(std::tie(keylist))}; + return detail::send_t{detail::broadcastk_coro(std::tie(keylist))}; } } diff --git a/ttg/ttg/parsec/task.h b/ttg/ttg/parsec/task.h index b44d636b05..92cbdccaf0 100644 --- a/ttg/ttg/parsec/task.h +++ b/ttg/ttg/parsec/task.h @@ -97,7 +97,8 @@ namespace ttg_parsec { struct stream_info_t { std::size_t goal; std::size_t size; - parsec_lifo_t reduce_copies; + std::mutex reduce_copies_lock; + std::vector reduce_copies; std::atomic reduce_count; }; @@ -108,7 +109,7 @@ namespace ttg_parsec { if (std::get(tt->input_reducers)) { streams[i].goal = tt->static_stream_goal[i]; streams[i].size = 0; - PARSEC_OBJ_CONSTRUCT(&streams[i].reduce_copies, parsec_lifo_t); + streams[i].reduce_copies.clear(); streams[i].reduce_count.store(0, std::memory_order_relaxed); } /* recursion */ diff --git a/ttg/ttg/parsec/ttg.h b/ttg/ttg/parsec/ttg.h index 616d90e792..7df4ffd3a0 100644 --- a/ttg/ttg/parsec/ttg.h +++ b/ttg/ttg/parsec/ttg.h @@ -1710,18 +1710,16 @@ namespace ttg_parsec { nullptr; #endif // TTG_HAVE_COROUTINE //std::cout << "static_op: suspended_task_address " << suspended_task_address << std::endl; + ttT *baseobj = task->tt; + derivedT *obj = static_cast(baseobj); + if constexpr (!ttg::meta::is_void_v) + ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : ", task->key, ": executing"); + else + ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : executing"); if (suspended_task_address == nullptr) { // task is a coroutine that has not started or an ordinary function - ttT *baseobj = task->tt; - derivedT *obj = static_cast(baseobj); assert(detail::parsec_ttg_caller == nullptr); detail::parsec_ttg_caller = static_cast(task); - if (obj->tracing()) { - if constexpr (!ttg::meta::is_void_v) - ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : ", task->key, ": executing"); - else - ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : executing"); - } if constexpr (!ttg::meta::is_void_v && !ttg::meta::is_empty_tuple_v) { auto input = make_tuple_of_ref_from_array(task, std::make_index_sequence{}); @@ -1890,12 +1888,12 @@ namespace ttg_parsec { if (rtask->is_first) { if (0 == (parent_task->streams[i].reduce_count.fetch_sub(1, std::memory_order_acq_rel)-1)) { /* we were the first and there is nothing to be done */ - if (obj->tracing()) { + //if (obj->tracing()) { if constexpr (!ttg::meta::is_void_v) ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : ", parent_task->key, ": first reducer empty"); else ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : first reducer empty"); - } + //} return PARSEC_HOOK_RETURN_DONE; } @@ -1908,13 +1906,19 @@ namespace ttg_parsec { if constexpr(!val_is_void) { /* the copies to reduce out of */ detail::ttg_data_copy_t *source_copy; - parsec_list_item_t *item; - item = parsec_lifo_pop(&parent_task->streams[i].reduce_copies); + detail::ttg_data_copy_t *item = nullptr; + { + std::lock_guard lock(parent_task->streams[i].reduce_copies_lock); + if (!parent_task->streams[i].reduce_copies.empty()) { + item = parent_task->streams[i].reduce_copies.back(); + parent_task->streams[i].reduce_copies.pop_back(); + } + } if (nullptr == item) { // maybe someone is changing the goal right now break; } - source_copy = ((detail::ttg_data_copy_self_t *)(item))->self; + source_copy = item; assert(target_copy->num_readers() == target_copy->mutable_tag); assert(source_copy->num_readers() > 0); reducer(*reinterpret_cast *>(target_copy->get_ptr()), @@ -1935,6 +1939,11 @@ namespace ttg_parsec { //std::cout << "static_reducer_op size " << size // << " of " << parent_task->streams[i].goal << " complete " << complete // << " c " << c << std::endl; + if constexpr (!ttg::meta::is_void_v) { + ttg::trace(obj->get_world().rank(), ":", obj->get_name(), " : ", parent_task->key, ": size ", size, " of ", parent_task->streams[i].goal, " complete ", complete, " c ", c); + } else { + ttg::trace(obj->get_world().rank(), ":", obj->get_name(), ": size ", size, " of ", parent_task->streams[i].goal, " complete ", complete, " c ", c); + } if (complete && c == 0) { if constexpr(input_is_const) { /* make the consumer task a reader if its input is const */ @@ -2595,7 +2604,10 @@ namespace ttg_parsec { detail::ttg_data_copy_t *copy = get_copy_fn(task, std::forward(value), true); /* enqueue the data copy to be reduced */ - parsec_lifo_push(&task->streams[i].reduce_copies, ©->super); + { + std::lock_guard lock(task->streams[i].reduce_copies_lock); + task->streams[i].reduce_copies.push_back(copy); + } submit_reducer_task(task); } } else {