<commit_before>#ifndef VSMC_HELPER_PARALLEL_TBB_HPP
#define VSMC_HELPER_PARALLEL_TBB_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/helper/base.hpp>
#include <tbb/tbb.h>

/// \defgroup TBB Intel Threading Buidling Block
/// \ingroup Helper
/// \brief Parallelized samplers with Intel TBB

namespace vsmc {

/// \brief Particle::value_type subtype
/// \ingroup TBB
///
/// \tparam Dim The dimension of the state parameter vector
/// \tparam T The type of the value of the state parameter vector
/// \tparam Profiler class The profiler used for profiling run_parallel().
/// The default is NullProfiler, which does nothing but provide the compatible
/// inteferce. Profiler::start() and Profiler::stop() are called automatically
/// when entering and exiting run_parallel(). This shall provide how much
/// time are spent on the parallel code (plus a small overhead of scheduling).
template <unsigned Dim, typename T, typename Profiler>
class StateTBB : public internal::StateBase<Dim, T>
#if !VSMC_HAS_CXX11_DECLTYPE || !VSMC_HAS_CXX11_AUTO_TYPE
    , public internal::ParallelTag
#endif
{
    public :

    typedef VSMC_SIZE_TYPE size_type;
    typedef T state_type;
    typedef Profiler profiler_type;

    explicit StateTBB (size_type N) :
        internal::StateBase<Dim, T>(N), size_(N), copy_(N) {}

    virtual ~StateTBB () {}

    /// \brief Run a worker in parallel with tbb::parallel_for
    ///
    /// \param work The worker object
    ///
    /// \note The kernel shall implement
    /// \code
    /// void operator () (const tbb::blocked_range<size_type> &range) const
    /// \endcode
    /// where \c size_type is StateTBB::size_type. There are equivalent
    /// typedefs in InitializeTBB etc.
    ///
    /// \note The range form of tbb::parallel_for is used by run_parallel.
    /// This is the most commonly used in the context of SMC. The range is
    /// constructed as <tt>tbb::blocked_range<size_type>(0, size())</tt>. For
    /// more complex parallel patterns, users need to call Intel TBB API
    /// themselves.
    template <typename Work>
    void run_parallel (const Work &work) const
    {
        profiler_.start();
        tbb::parallel_for(tbb::blocked_range<size_type>(0, size_), work);
        profiler_.stop();
    }

    /// \brief Run a worker in parallel with tbb::parallel_for
    ///
    /// \param work The worker object
    /// \param part The affinity partitioner
    template <typename Work>
    void run_parallel (const Work &work, tbb::affinity_partitioner &part) const
    {
        profiler_.start();
        tbb::parallel_for(tbb::blocked_range<size_type>(0, size_), work, part);
        profiler_.stop();
    }

    Profiler &profiler () const
    {
        return profiler_;
    }

    void copy (size_type from, size_type to)
    {
        copy_[to] = from;
    }

    void pre_resampling ()
    {
        for (size_type i = 0; i != this->size(); ++i)
            copy_[i] = i;
    }

    void post_resampling ()
    {
        run_parallel(copy_work_(this, copy_.data()));
    }

    private :

    size_type size_;
    std::vector<size_type> copy_;<commit_msg>add some more doc on affinity<commit_after>#ifndef VSMC_HELPER_PARALLEL_TBB_HPP
#define VSMC_HELPER_PARALLEL_TBB_HPP

#include <vsmc/internal/common.hpp>
#include <vsmc/helper/base.hpp>
#include <tbb/tbb.h>

/// \defgroup TBB Intel Threading Buidling Block
/// \ingroup Helper
/// \brief Parallelized samplers with Intel TBB

namespace vsmc {

/// \brief Particle::value_type subtype
/// \ingroup TBB
///
/// \tparam Dim The dimension of the state parameter vector
/// \tparam T The type of the value of the state parameter vector
/// \tparam Profiler class The profiler used for profiling run_parallel().
/// The default is NullProfiler, which does nothing but provide the compatible
/// inteferce. Profiler::start() and Profiler::stop() are called automatically
/// when entering and exiting run_parallel(). This shall provide how much
/// time are spent on the parallel code (plus a small overhead of scheduling).
template <unsigned Dim, typename T, typename Profiler>
class StateTBB : public internal::StateBase<Dim, T>
#if !VSMC_HAS_CXX11_DECLTYPE || !VSMC_HAS_CXX11_AUTO_TYPE
    , public internal::ParallelTag
#endif
{
    public :

    typedef VSMC_SIZE_TYPE size_type;
    typedef T state_type;
    typedef Profiler profiler_type;

    explicit StateTBB (size_type N) :
        internal::StateBase<Dim, T>(N), size_(N), copy_(N) {}

    virtual ~StateTBB () {}

    /// \brief Run a worker in parallel with tbb::parallel_for
    ///
    /// \param work The worker object
    ///
    /// \note The kernel shall implement
    /// \code
    /// void operator () (const tbb::blocked_range<size_type> &range) const
    /// \endcode
    /// where \c size_type is StateTBB::size_type. There are equivalent
    /// typedefs in InitializeTBB etc.
    ///
    /// \note The range form of tbb::parallel_for is used by run_parallel.
    /// This is the most commonly used in the context of SMC. The range is
    /// constructed as <tt>tbb::blocked_range<size_type>(0, size())</tt>. For
    /// more complex parallel patterns, users need to call Intel TBB API
    /// themselves.
    template <typename Work>
    void run_parallel (const Work &work) const
    {
        profiler_.start();
        tbb::parallel_for(tbb::blocked_range<size_type>(0, size_), work);
        profiler_.stop();
    }

    /// \brief Run a worker in parallel with tbb::parallel_for
    ///
    /// \param work The worker object
    /// \param ap The affinity partitioner
    ///
    /// \note This is only useful when the all the data can fit into system
    /// cache and the computation to memeory access ratio is low. This is
    /// usually not common in an SMC sampler. There can be situations that
    /// such operations appears, for example, a simple Monitor. But usually
    /// these operations cost such a small fraction of time of the whole
    /// sampler that we don't find they worth the time of optimization.
    template <typename Work>
    void run_parallel (const Work &work, tbb::affinity_partitioner &ap) const
    {
        profiler_.start();
        tbb::parallel_for(tbb::blocked_range<size_type>(0, size_), work, ap);
        profiler_.stop();
    }

    Profiler &profiler () const
    {
        return profiler_;
    }

    void copy (size_type from, size_type to)
    {
        copy_[to] = from;
    }

    void pre_resampling ()
    {
        for (size_type i = 0; i != this->size(); ++i)
            copy_[i] = i;
    }

    void post_resampling ()
    {
        run_parallel(copy_work_(this, copy_.data()));
    }

    private :

    size_type size_;
    std::vector<size_type> copy_;
{'fraction_non_alphanumeric': 0.11248510131108462, 'fraction_numerical': 0.0023837902264600714, 'mean_word_length': 2.7713483146067417, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5900616', 'n_tokens_mistral': 2071, 'n_tokens_neox': 2043, 'n_words': 677}