Skip to content

Commit

Permalink
test std::generator(co_yield elements_of)/std::generator(for generato…
Browse files Browse the repository at this point in the history
…r)/oeo::generator(no coroutine stack) performance at different depths
  • Loading branch information
CST18057 committed Oct 31, 2024
1 parent 6208ac8 commit 64c300b
Show file tree
Hide file tree
Showing 4 changed files with 528 additions and 2 deletions.
19 changes: 17 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
endif()

set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -g -O3 -ffast-math -Wall -march=native -fno-omit-frame-pointer")
"${CMAKE_CXX_FLAGS} -g -O3 -ffast-math -Wall -march=native ")

CPMAddPackage(
NAME benchmark
Expand All @@ -37,4 +37,19 @@ target_compile_features(bm_hamming_weight32 PRIVATE cxx_std_20)

add_executable(bm_histgram "histgram/histgram.cc")
target_link_libraries(bm_histgram benchmark)
target_compile_features(bm_histgram PRIVATE cxx_std_20)
target_compile_features(bm_histgram PRIVATE cxx_std_20)


add_executable(bm_gen_recursive_short "generator_recursive/main.cpp")
add_executable(bm_gen_recursive_middle "generator_recursive/main.cpp")
add_executable(bm_gen_recursive_long "generator_recursive/main.cpp")
target_compile_definitions(bm_gen_recursive_short PRIVATE TEST_SHORT)
target_compile_definitions(bm_gen_recursive_middle PRIVATE TEST_MIDDLE)
target_compile_definitions(bm_gen_recursive_long PRIVATE TEST_LONG)
target_compile_options(bm_gen_recursive_long PRIVATE -fomit-frame-pointer)
target_link_libraries(bm_gen_recursive_short benchmark)
target_link_libraries(bm_gen_recursive_middle benchmark)
target_link_libraries(bm_gen_recursive_long benchmark)
target_compile_features(bm_gen_recursive_short PRIVATE cxx_std_23)
target_compile_features(bm_gen_recursive_middle PRIVATE cxx_std_23)
target_compile_features(bm_gen_recursive_long PRIVATE cxx_std_23)
131 changes: 131 additions & 0 deletions generator_recursive/generator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// 此实现来自群友@OEOTYAN
#ifndef __GENERATOR_HPP__
#define __GENERATOR_HPP__
#pragma once

#include <concepts>
#include <coroutine>
#include <cstddef>
#include <exception>
#include <type_traits>
#include <utility>
#include <iterator>

namespace oeo {

template <class T>
struct generator {
using value = std::remove_cvref_t<T>;
using reference = T&&;
using yielded = reference;


struct promise_type {
std::add_pointer_t<yielded> ptr;
std::exception_ptr exception;

generator get_return_object() noexcept { return generator{*this}; }

std::suspend_always initial_suspend() noexcept { return {}; }

std::suspend_always final_suspend() noexcept { return {}; }

void unhandled_exception() noexcept { exception = std::current_exception(); }

void rethrow() {
if (exception) {
std::rethrow_exception(exception);
}
}
std::suspend_always yield_value(yielded val) noexcept {
ptr = std::addressof(val);
return {};
}
auto yield_value(std::remove_reference_t<yielded> const& lval)
requires std::is_rvalue_reference_v<yielded> &&
std::constructible_from<std::remove_cvref_t<yielded>, std::remove_reference_t<yielded> const&>
{
struct yield_copied {
std::remove_cvref_t<yielded> storage;
constexpr yield_copied(std::remove_reference_t<yielded> const& v) : storage(v) {}
constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(std::coroutine_handle<promise_type> h) noexcept {
h.promise().ptr = std::addressof(storage);
}
constexpr void await_resume() const noexcept {}
};
return yield_copied{lval};
}
void return_void() noexcept {}

template <class U>
U&& await_transform(U&&) = delete;
};

struct iterator {
using iterator_category = std::input_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = generator::value;
using reference = generator::reference;
using pointer = std::add_pointer_t<yielded>;

std::coroutine_handle<promise_type> handle = nullptr;

iterator() = default;
explicit iterator(std::coroutine_handle<promise_type> handle) noexcept : handle(handle) {}

iterator& operator++() {
handle.resume();
if (handle.done()) {
std::exchange(handle, nullptr).promise().rethrow();
}

return *this;
}

void operator++(int) { ++*this; }

[[nodiscard]] bool operator==(iterator const& other) const noexcept { return handle == other.handle; }

[[nodiscard]] bool operator!=(iterator const& other) const noexcept { return !(*this == other); }

[[nodiscard]] reference operator*() const noexcept { return static_cast<reference>(*handle.promise().ptr); }

[[nodiscard]] pointer operator->() const noexcept { return handle.promise().ptr; }
};
[[nodiscard]] iterator begin() {
if (handle) {
handle.resume();
if (handle.done()) {
handle.promise().rethrow();
return {};
}
}
return iterator{handle};
}

[[nodiscard]] iterator end() noexcept { return {}; }

constexpr generator(generator&& other) noexcept : handle(std::exchange(other.handle, nullptr)) {}

constexpr ~generator() {
if (handle) {
handle.destroy();
}
}
constexpr generator() = default;

generator& operator=(generator&& other) noexcept {
std::swap(other.handle, handle);
return *this;
}

private:
constexpr explicit generator(promise_type& promise) noexcept
: handle(std::coroutine_handle<promise_type>::from_promise(promise)) {}

std::coroutine_handle<promise_type> handle = nullptr;
};
} // namespace oeo

#endif /* __GENERATOR_HPP__ */
Loading

0 comments on commit 64c300b

Please sign in to comment.