diff options
author | 2020-06-28 13:13:57 +0200 | |
---|---|---|
committer | 2020-06-28 13:14:42 +0200 | |
commit | 3fcdfa0a9b1783f556abe36c9fb927c25c2170ee (patch) | |
tree | 321f4d3c3e080448f020ee3d037abe6b453a511e | |
parent | 3832644d4ad36d5b5807b3d2d9ff6d284bd86236 (diff) |
netlist: code maintenance
* decrease use of reinterpret_cast.
* change some defaults for better ttl game optimization.
* various code cleanup.
-rw-r--r-- | src/lib/netlist/nl_base.h | 9 | ||||
-rw-r--r-- | src/lib/netlist/plib/mat_cr.h | 26 | ||||
-rw-r--r-- | src/lib/netlist/plib/pconfig.h | 19 | ||||
-rw-r--r-- | src/lib/netlist/plib/plists.h | 3 | ||||
-rwxr-xr-x | src/lib/netlist/plib/pmatrix2d.h | 7 | ||||
-rw-r--r-- | src/lib/netlist/plib/pmempool.h | 5 | ||||
-rw-r--r-- | src/lib/netlist/plib/pstream.h | 39 | ||||
-rw-r--r-- | src/lib/netlist/plib/ptimed_queue.h | 1 | ||||
-rwxr-xr-x | src/lib/netlist/prg/nlwav.cpp | 4 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_matrix_solver.h | 2 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_ms_gcr.h | 9 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 15 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_solver.h | 9 |
13 files changed, 105 insertions, 43 deletions
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index e3e764b6d90..e18c44df9a6 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -1372,7 +1372,7 @@ namespace netlist protected: void changed() noexcept override { - stream()->read(reinterpret_cast<std::istream::char_type *>(&m_data[0]),1<<AW); + plib::istream_read(*stream(), m_data.data(), 1<<AW); } private: @@ -1940,11 +1940,12 @@ namespace netlist devices::NETLIB_NAME(solver) * m_solver; // mostly rw - PALIGNAS_CACHELINE() + //PALIGNAS(16) netlist_time_ext m_time; devices::NETLIB_NAME(mainclock) * m_mainclock; - PALIGNAS_CACHELINE() + //PALIGNAS_CACHELINE() + //PALIGNAS(16) detail::queue_t m_queue; bool m_use_stats; // performance @@ -2552,7 +2553,7 @@ namespace netlist auto f = stream(); if (f != nullptr) { - f->read(reinterpret_cast<std::istream::char_type *>(&m_data[0]),1<<AW); + plib::istream_read(*f, m_data.data(), 1<<AW); // FIXME: check for failbit if not in validation. } else diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h index 2da661d39d7..0f21aff2326 100644 --- a/src/lib/netlist/plib/mat_cr.h +++ b/src/lib/netlist/plib/mat_cr.h @@ -18,6 +18,7 @@ #include "pstate.h" #include "ptypes.h" #include "putil.h" +#include "pmatrix2d.h" #include <algorithm> #include <array> @@ -62,7 +63,7 @@ namespace plib , A(n*n) , nz_num(0) //, nzbd(n * (n+1) / 2) - , nzbd(n) + , m_nzbd(n, n) , m_size(n) { for (std::size_t i=0; i<n+1; i++) @@ -148,10 +149,17 @@ namespace plib for (std::size_t k=0; k < size(); k++) { +#if 0 for (std::size_t j=k + 1; j < size(); j++) if (f[j][k] < FILL_INFINITY) - nzbd[k].push_back(narrow_cast<C>(j)); - nzbd[k].push_back(0); // end of sequence + m_nzbd[k].push_back(narrow_cast<C>(j)); + m_nzbd[k].push_back(0); // end of sequence +#else + for (std::size_t j=k + 1; j < size(); j++) + if (f[j][k] < FILL_INFINITY) + m_nzbd.set(k, m_nzbd.colcount(k), narrow_cast<C>(j)); + m_nzbd.set(k, m_nzbd.colcount(k), 0); // end of sequence +#endif } } @@ -241,10 +249,13 @@ namespace plib A[k] = src.A[k]; } + index_type * nzbd(index_type row) { return m_nzbd[row]; } + index_type nzbd_count(index_type row) { return m_nzbd.colcount(row) - 1; } protected: // FIXME: this should be private // NOLINTNEXTLINE - parray<std::vector<index_type>, N > nzbd; // Support for gaussian elimination + //parray<std::vector<index_type>, N > m_nzbd; // Support for gaussian elimination + pmatrix2d_vrl<index_type> m_nzbd; // Support for gaussian elimination private: //parray<C, N < 0 ? -N * (N-1) / 2 : N * (N+1) / 2 > nzbd; // Support for gaussian elimination std::size_t m_size; @@ -309,9 +320,14 @@ namespace plib std::size_t pi = base::diag[i]; auto f = reciprocal(base::A[pi++]); const std::size_t piie = base::row_idx[i+1]; - const auto &nz = base::nzbd[i]; +#if 0 + const auto &nz = base::m_nzbd[i]; while (auto j = nz[nzbdp++]) // NOLINT(bugprone-infinite-loop) +#else + const auto *nz = base::m_nzbd[i]; + while (auto j = nz[nzbdp++]) // NOLINT(bugprone-infinite-loop) +#endif { // proceed to column i diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index 984ed944acb..99643139de7 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -41,7 +41,7 @@ /// Set this to one if you want to use aligned storage optimizations. /// #ifndef PUSE_ALIGNED_OPTIMIZATIONS -#define PUSE_ALIGNED_OPTIMIZATIONS (0) +#define PUSE_ALIGNED_OPTIMIZATIONS (1) #endif /// \brief Use aligned allocations. @@ -63,15 +63,28 @@ /// \brief Number of bytes for cache line alignment /// -#define PALIGN_CACHELINE (16) +#define PALIGN_CACHELINE (64) /// \brief Number of bytes for vector alignment /// -#define PALIGN_VECTOROPT (16) +#define PALIGN_VECTOROPT (32) + +#define PALIGN_MIN_SIZE (16) #define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE) #define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT) +/// brief default minimum alignment of mempool_arena +/// +/// 256 is the best compromise between logic applications like MAME +/// TTL games (e.g. pong) and analog applications like e.g. kidnikik sound. +/// +/// Best performance for pong is achieved with a value of 16, but this degrades +/// kidniki performance by ~10%. +/// +/// More work is needed here. +#define PMEMPOOL_ALIGN (256) + // FIXME: Breaks mame build on windows mingw due to -Wattribute // also triggers -Wattribute on ARM // This is fixed on mingw version 10 diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h index 4e3ddace57e..f23caa18c2c 100644 --- a/src/lib/netlist/plib/plists.h +++ b/src/lib/netlist/plib/plists.h @@ -98,9 +98,6 @@ namespace plib { protected: private: - - // ensure proper alignment - PALIGNAS_VECTOROPT() std::array<typename std::aligned_storage<sizeof(C), alignof(C)>::type, N> m_buf; unsigned m_initialized; }; diff --git a/src/lib/netlist/plib/pmatrix2d.h b/src/lib/netlist/plib/pmatrix2d.h index b9a2ebee116..0b982b8a034 100755 --- a/src/lib/netlist/plib/pmatrix2d.h +++ b/src/lib/netlist/plib/pmatrix2d.h @@ -214,7 +214,12 @@ namespace plib return m_row[r] + c; } - std::size_t tx() const { return m_v.size(); } + size_type colcount(size_type row) const noexcept + { + return m_row[row + 1] - m_row[row]; + } + + size_type tx() const { return m_v.size(); } private: size_type m_N; diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 033a622ff3b..d66efe2abdd 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -27,7 +27,7 @@ namespace plib { // Memory pool //============================================================ - template <typename BASEARENA> + template <typename BASEARENA, std::size_t MINALIGN = PMEMPOOL_ALIGN> class mempool_arena : public arena_base<mempool_arena<BASEARENA>, false, false> { public: @@ -37,7 +37,7 @@ namespace plib { template <class T> using base_allocator_type = typename BASEARENA::template allocator_type<T>; - mempool_arena(size_t min_alloc = (1<<21), size_t min_align = PALIGN_CACHELINE) + mempool_arena(size_t min_align = MINALIGN, size_t min_alloc = (1<<21)) : m_min_alloc(min_alloc) , m_min_align(min_align) , m_block_align(1024) @@ -70,6 +70,7 @@ namespace plib { align = m_min_align; size_t rs = size + align; + for (auto &bs : m_blocks) { if (bs->m_free > rs) diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h index b96c1f91a3b..dcb2b0652cf 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -27,8 +27,29 @@ namespace plib { + /// \brief wrapper around isteam read + /// + template <typename S, typename T> + static inline S & istream_read(S &is, T * data, size_t len) + { + using ct = typename S::char_type; + static_assert((sizeof(T) % sizeof(ct)) == 0, "istream_read sizeof issue"); + // FIXME: throw on + return is.read(reinterpret_cast<ct *>(data), gsl::narrow<std::streamsize>(len * sizeof(T))); + } + + /// \brief wrapper around osteam write + /// + template <typename S, typename T> + static inline S & ostream_write(S &os, const T * data, size_t len) + { + using ct = typename S::char_type; + static_assert((sizeof(T) % sizeof(ct)) == 0, "ostream_write sizeof issue"); + // FIXME: throw on + return os.write(reinterpret_cast<const ct *>(data), gsl::narrow<std::streamsize>(len * sizeof(T))); + } + /// -/// \brief: putf8reader_t: reader on top of istream. /// /// putf8reader_t digests linux & dos/windows text files /// @@ -188,23 +209,23 @@ public: template <typename T> void write(const T &val) { - m_strm.write(reinterpret_cast<const std::ostream::char_type *>(&val), sizeof(T)); + ostream_write(m_strm, &val, 1); } void write(const pstring &s) { - const auto *const sm = reinterpret_cast<const std::ostream::char_type *>(s.c_str()); - const auto sl(static_cast<std::streamsize>(std::char_traits<std::ostream::char_type>::length(sm))); + auto *sm = s.c_str(); + const auto sl(std::char_traits<pstring::mem_t>::length(sm)); write(sl); - m_strm.write(sm, sl); + ostream_write(m_strm, sm, sl); } template <typename T> void write(const std::vector<T> &val) { - const auto sz(static_cast<std::streamsize>(val.size())); + const auto sz(val.size()); write(sz); - m_strm.write(reinterpret_cast<const std::ostream::char_type *>(val.data()), sz * gsl::narrow<std::streamsize>(sizeof(T))); + ostream_write(m_strm, val.data(), sz); } private: @@ -225,7 +246,7 @@ public: template <typename T> void read(T &val) { - m_strm.read(reinterpret_cast<std::istream::char_type *>(&val), gsl::narrow<std::streamsize>(sizeof(T))); + istream_read(m_strm, &val, 1); } void read( pstring &s) @@ -244,7 +265,7 @@ public: std::size_t sz = 0; read(sz); val.resize(sz); - m_strm.read(reinterpret_cast<std::istream::char_type *>(val.data()), gsl::narrow<std::streamsize>(sizeof(T) * sz)); + istream_read(m_strm, val.data(), sz); } private: diff --git a/src/lib/netlist/plib/ptimed_queue.h b/src/lib/netlist/plib/ptimed_queue.h index dffc969e9c6..2ec158f316e 100644 --- a/src/lib/netlist/plib/ptimed_queue.h +++ b/src/lib/netlist/plib/ptimed_queue.h @@ -217,7 +217,6 @@ namespace plib { using lock_guard_type = std::lock_guard<mutex_type>; mutex_type m_lock; - PALIGNAS_CACHELINE() T * m_end; aligned_vector<T> m_list; diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp index 2317495c677..9a9b3f08e69 100755 --- a/src/lib/netlist/prg/nlwav.cpp +++ b/src/lib/netlist/prg/nlwav.cpp @@ -76,9 +76,7 @@ public: template <typename T> void write(const T &val) { - static_assert(sizeof(std::ostream::char_type) == 1, "char_type size must be 1"); - const auto *ptr(reinterpret_cast<const std::ostream::char_type *>(&val)); - m_f.write(ptr, sizeof(T)); + plib::ostream_write(m_f, &val, 1); } template <typename T> diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index 6a769775248..3fd0e2fd6d9 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -185,7 +185,7 @@ namespace solver public: using list_t = std::vector<matrix_solver_t *>; using fptype = nl_fptype; - using arena_type = plib::mempool_arena<plib::aligned_arena>; + using arena_type = plib::mempool_arena<plib::aligned_arena, PALIGN_VECTOROPT>; // after every call to solve, update inputs must be called. // this can be done as well as a batch to ease parallel processing. diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index 3de955627ee..fb5c675dd14 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -200,9 +200,11 @@ namespace solver for (std::size_t i = 0; i < iN - 1; i++) { - const auto &nzbd = this->m_terms[i].m_nzbd; + //const auto &nzbd = this->m_terms[i].m_nzbd; + const auto *nzbd = mat.nzbd(i); + const auto nzbd_count = mat.nzbd_count(i); - if (!nzbd.empty()) + if (nzbd_count > 0) { std::size_t pi = mat.diag[i]; @@ -212,8 +214,9 @@ namespace solver const std::size_t piie = mat.row_idx[i+1]; //for (auto & j : nzbd) - for (std::size_t j : nzbd) + for (std::size_t jj = 0; jj < nzbd_count; jj++) { + std::size_t j = nzbd[jj]; // proceed to column i std::size_t pj = mat.row_idx[j]; diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 4e0d8f4c4b3..b38616945f9 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -81,17 +81,20 @@ namespace devices } } + //using solver_ptr = host_arena::unique_ptr<solver::matrix_solver_t>; + // FIXME: should be created in device space template <class C> - host_arena::unique_ptr<solver::matrix_solver_t> create_it(netlist_state_t &nl, pstring name, + NETLIB_NAME(solver)::solver_ptr create_it(netlist_state_t &nl, pstring name, analog_net_t::list_t &nets, solver::solver_parameters_t ¶ms, std::size_t size) { return plib::make_unique<C, host_arena>(nl, name, nets, ¶ms, size); + //return nl.make_pool_object<C>(nl, name, nets, ¶ms, size); } template <typename FT, int SIZE> - host_arena::unique_ptr<solver::matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, + NETLIB_NAME(solver)::solver_ptr NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername, analog_net_t::list_t &nets) { @@ -124,11 +127,11 @@ namespace devices return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(state(), solvername, nets, m_params, size); #endif } - return host_arena::unique_ptr<solver::matrix_solver_t>(); + return solver_ptr(); } template <typename FT> - host_arena::unique_ptr<solver::matrix_solver_t> NETLIB_NAME(solver)::create_solvers( + NETLIB_NAME(solver)::solver_ptr NETLIB_NAME(solver)::create_solvers( const pstring &sname, analog_net_t::list_t &nets) { @@ -137,8 +140,10 @@ namespace devices { case 1: return plib::make_unique<solver::matrix_solver_direct1_t<FT>, host_arena>(state(), sname, nets, &m_params); + //return state().make_pool_object<solver::matrix_solver_direct1_t<FT>>(state(), sname, nets, &m_params); case 2: return plib::make_unique<solver::matrix_solver_direct2_t<FT>, host_arena>(state(), sname, nets, &m_params); + //return state().make_pool_object<solver::matrix_solver_direct2_t<FT>>(state(), sname, nets, &m_params); case 3: return create_solver<FT, 3>(3, sname, nets); case 4: @@ -291,7 +296,7 @@ namespace devices log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size()); for (auto & grp : splitter.groups) { - host_arena::unique_ptr<solver::matrix_solver_t> ms; + solver_ptr ms; pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); switch (m_params.m_fp_type()) diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index e9734af1520..f1395543524 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -47,23 +47,26 @@ namespace devices NETLIB_RESETI(); // NETLIB_UPDATE_PARAMI(); + //using solver_ptr = device_arena::unique_ptr<solver::matrix_solver_t>; + using solver_ptr = host_arena::unique_ptr<solver::matrix_solver_t>; + private: logic_input_t m_fb_step; logic_output_t m_Q_step; // FIXME: these should be created in device space - std::vector<host_arena::unique_ptr<solver::matrix_solver_t>> m_mat_solvers; + std::vector<solver_ptr> m_mat_solvers; std::vector<solver::matrix_solver_t *> m_mat_solvers_all; std::vector<solver::matrix_solver_t *> m_mat_solvers_timestepping; solver::solver_parameters_t m_params; template <typename FT, int SIZE> - host_arena::unique_ptr<solver::matrix_solver_t> create_solver(std::size_t size, + solver_ptr create_solver(std::size_t size, const pstring &solvername, analog_net_t::list_t &nets); template <typename FT> - host_arena::unique_ptr<solver::matrix_solver_t> create_solvers( + solver_ptr create_solvers( const pstring &sname, analog_net_t::list_t &nets); }; |