Ejemplo n.º 1
0
// policy: callback whenever i~k but not j~k
void BinaryRelation::unsafe_merge (Ob i)
{
    Ob j = carrier().find(i);
    POMAGMA_ASSERT4(j < i, "BinaryRelation tried to merge item with self");

    DenseSet diff(item_dim());
    DenseSet rep(item_dim(), nullptr);
    DenseSet dep(item_dim(), nullptr);

    // merge rows (i, _) into (j, _)
    dep.init(m_lines.Lx(i));
    _remove_Rx(i, dep);
    rep.init(m_lines.Lx(j));
    if (rep.merge(dep, diff)) {
        for (auto k = diff.iter(); k.ok(); k.next()) {
            _insert_Rx(j, *k);
        }
    }

    // merge cols (_, i) into (_, j)
    dep.init(m_lines.Rx(i));
    _remove_Lx(dep, i);
    rep.init(m_lines.Rx(j));
    if (rep.merge(dep, diff)) {
        for (auto k = diff.iter(); k.ok(); k.next()) {
            _insert_Lx(*k, j);
        }
    }
}
Ejemplo n.º 2
0
void Carrier::unsafe_remove (const Ob ob)
{
    UniqueLock lock(m_mutex);

    POMAGMA_ASSERT2(m_support.contains(ob), "double removal: " << ob);
    Ob rep = ob;
    while (not m_reps[rep].compare_exchange_strong(rep, rep)) {}
    POMAGMA_ASSERT2(rep, "double removal: " << ob);
    if (rep == ob) {
        for (Ob other = ob + 1, end = item_dim(); other <= end; ++other) {
            POMAGMA_ASSERT2(m_reps[other].load() != ob,
                    "removed rep " << ob << " before dep " << other);
        }
        --m_rep_count;
    } else {
        for (Ob other = ob + 1, end = item_dim(); other <= end; ++other) {
            Ob expected = ob;
            m_reps[other].compare_exchange_strong(expected, rep);
        }
    }

    m_support.remove(ob);
    m_reps[ob].store(0);
    --m_item_count;
    POMAGMA_DEBUG1(m_item_count.load() << " obs after remove()");
}
Ejemplo n.º 3
0
Ob Carrier::try_insert () const
{
    SharedLock lock(m_mutex);

    while (item_count() < item_dim()) {
        for (Ob ob = 1, end = item_dim(); ob <= end; ++ob) {
            Ob zero = 0;
            // This could be optimized using m_support iteration.
            // See DenseSet::try_insert for example low-level code.
            bool inserted = m_reps[ob].compare_exchange_strong(
                    zero,
                    ob,
                    std::memory_order_acq_rel,
                    std::memory_order_acquire);
            if (unlikely(inserted)) {
                m_support.insert(ob, std::memory_order_release);
                ++m_item_count;
                ++m_rep_count;
                if (m_insert_callback) {
                    m_insert_callback(ob);
                }
                // The following triggers a weird gcc bug or something
                // error: invalid memory model for ‘__atomic_load
                //POMAGMA_DEBUG1(m_item_count.load() << " obs after insert()");
                return ob;
            }
        }
    }

    return 0;
}
Ejemplo n.º 4
0
void SymmetricFunction::validate() const {
    POMAGMA_INFO("Validating SymmetricFunction");

    m_lines.validate();

    POMAGMA_DEBUG("validating line-value consistency");
    for (size_t i = 1; i <= item_dim(); ++i)
        for (size_t j = i; j <= item_dim(); ++j) {
            auto val_iter = m_values.find(assert_sorted_pair(i, j));

            if (not(support().contains(i) and support().contains(j))) {
                POMAGMA_ASSERT(val_iter == m_values.end(),
                               "found unsupported lhs, rhs: " << i << ',' << j);
            } else if (val_iter != m_values.end()) {
                POMAGMA_ASSERT(defined(i, j),
                               "found undefined value: " << i << ',' << j);
                Ob val = val_iter->second;
                POMAGMA_ASSERT(val, "found zero value: " << i << ',' << j);
                POMAGMA_ASSERT(support().contains(val),
                               "found unsupported value: " << i << ',' << j);
            } else {
                POMAGMA_ASSERT(not defined(i, j),
                               "found defined null value: " << i << ',' << j);
            }
        }
}
Ejemplo n.º 5
0
inline oid_t dense_bin_fun::value (oid_t i, oid_t j) const
{
    POMAGMA_ASSERT_RANGE_(5, i, item_dim());
    POMAGMA_ASSERT_RANGE_(5, j, item_dim());

    const oid_t * block = _block(i / ITEMS_PER_BLOCK, j / ITEMS_PER_BLOCK);
    return _block2value(block, i & BLOCK_POS_MASK, j & BLOCK_POS_MASK);
}
Ejemplo n.º 6
0
void BinaryRelation::insert(Ob i, const DenseSet& js) {
    DenseSet diff(item_dim());
    DenseSet dest(item_dim(), m_lines.Lx(i));
    if (dest.ensure(js, diff)) {
        for (auto k = diff.iter(); k.ok(); k.next()) {
            _insert_Rx(i, *k);
        }
    }
}
Ejemplo n.º 7
0
void BinaryRelation::insert(const DenseSet& is, Ob j) {
    DenseSet diff(item_dim());
    DenseSet dest(item_dim(), m_lines.Rx(j));
    if (dest.ensure(is, diff)) {
        for (auto k = diff.iter(); k.ok(); k.next()) {
            _insert_Lx(*k, j);
        }
    }
}
Ejemplo n.º 8
0
void BinaryFunction::unsafe_merge(const Ob dep) {
    POMAGMA_ASSERT5(support().contains(dep), "unsupported dep: " << dep);
    Ob rep = carrier().find(dep);
    POMAGMA_ASSERT5(support().contains(rep), "unsupported rep: " << rep);
    POMAGMA_ASSERT4(rep != dep, "self merge: " << dep << "," << rep);

    // Note: in some cases, triples may move multiple times, e.g.
    //   (dep, dep) --> (dep, rep) --> (rep, rep)

    // dep as rhs
    for (auto iter = iter_rhs(dep); iter.ok(); iter.next()) {
        Ob lhs = *iter;
        auto dep_iter = m_values.find(std::make_pair(lhs, dep));
        Ob dep_val = dep_iter->second;
        m_values.erase(dep_iter);
        m_lines.Lx(lhs, dep).zero();
        Ob& rep_val = m_values[std::make_pair(lhs, rep)];
        if (carrier().set_or_merge(rep_val, dep_val)) {
            m_lines.Lx(lhs, rep).one();
        }
    }
    {
        DenseSet dep_set(item_dim(), m_lines.Rx(dep));
        DenseSet rep_set(item_dim(), m_lines.Rx(rep));
        rep_set.merge(dep_set);
    }

    // dep as lhs
    rep = carrier().find(rep);
    for (auto iter = iter_lhs(dep); iter.ok(); iter.next()) {
        Ob rhs = *iter;
        auto dep_iter = m_values.find(std::make_pair(dep, rhs));
        Ob dep_val = dep_iter->second;
        m_values.erase(dep_iter);
        m_lines.Rx(dep, rhs).zero();
        Ob& rep_val = m_values[std::make_pair(rep, rhs)];
        if (carrier().set_or_merge(rep_val, dep_val)) {
            m_lines.Rx(rep, rhs).one();
        }
    }
    {
        DenseSet dep_set(item_dim(), m_lines.Lx(dep));
        DenseSet rep_set(item_dim(), m_lines.Lx(rep));
        rep_set.merge(dep_set);
    }

    // values must be updated in batch by update_values
}
Ejemplo n.º 9
0
void Carrier::validate () const
{
    UniqueLock lock(m_mutex);

    POMAGMA_INFO("Validating Carrier");

    m_support.validate();

    size_t actual_item_count = 0;
    size_t actual_rep_count = 0;
    for (Ob i = 1; i <= item_dim(); ++i) {
        Ob rep = m_reps[i].load();
        if (contains(i)) {
            POMAGMA_ASSERT(rep, "supported object has no rep: " << i);
            POMAGMA_ASSERT(rep <= i, "rep out of order: " << rep << "," << i);
            ++actual_item_count;
            if (rep == i) {
                ++actual_rep_count;
            }
        } else {
            POMAGMA_ASSERT(rep == 0, "unsupported object has rep: " << i);
        }
    }
    POMAGMA_ASSERT_EQ(item_count(), actual_item_count);
    POMAGMA_ASSERT_EQ(rep_count(), actual_rep_count);
}
Ejemplo n.º 10
0
void Carrier::clear ()
{
    memory_barrier();
    m_support.zero();
    zero_blocks(m_reps, 1 + item_dim());
    m_rep_count = 0;
    m_item_count = 0;
    memory_barrier();
}
Ejemplo n.º 11
0
void BinaryRelation::validate_disjoint(const BinaryRelation& other) const {
    POMAGMA_INFO("Validating disjoint pair of BinaryRelations");

    // validate supports agree
    POMAGMA_ASSERT_EQ(support().item_dim(), other.support().item_dim());
    POMAGMA_ASSERT_EQ(support().count_items(), other.support().count_items());
    POMAGMA_ASSERT(support() == other.support(),
                   "BinaryRelation supports differ");

    // validate disjointness
    DenseSet this_set(item_dim(), nullptr);
    DenseSet other_set(item_dim(), nullptr);
    for (auto i = support().iter(); i.ok(); i.next()) {
        this_set.init(m_lines.Lx(*i));
        other_set.init(other.m_lines.Lx(*i));
        POMAGMA_ASSERT(this_set.disjoint(other_set),
                       "BinaryRelations intersect at row " << *i);
    }
}
Ejemplo n.º 12
0
inline bool Carrier::set_and_merge(std::atomic<Ob>& destin, Ob source) const {
    POMAGMA_ASSERT_RANGE_(5, source, item_dim());

    Ob old = 0;
    while (not destin.compare_exchange_strong(
        old, source, std::memory_order_acq_rel, std::memory_order_acquire)) {
        source = ensure_equal(source, old);
        if (old == source) return false;
    }
    return old == 0;
}
Ejemplo n.º 13
0
inline bool Carrier::set_or_merge(std::atomic<Ob>& destin, Ob source) const {
    POMAGMA_ASSERT_RANGE_(5, source, item_dim());

    Ob old = 0;
    if (destin.compare_exchange_strong(old, source, std::memory_order_acq_rel,
                                       std::memory_order_acquire)) {
        return true;
    } else {
        ensure_equal(source, old);
        return false;
    }
}
Ejemplo n.º 14
0
void BinaryRelation::validate () const
{
    POMAGMA_INFO("Validating BinaryRelation");

    m_lines.validate();

    size_t num_pairs = 0;

    DenseSet Lx(round_item_dim(), nullptr);
    DenseSet Rx(round_item_dim(), nullptr);
    for (Ob i = 1; i <= item_dim(); ++i) {
        bool sup_i = supports(i);
        Lx.init(m_lines.Lx(i));

        for (Ob j = 1; j <= item_dim(); ++j) {
            bool sup_ij = sup_i and supports(j);
            Rx.init(m_lines.Rx(j));

            bool Lx_ij = Lx.contains(j);
            bool Rx_ij = Rx.contains(i);
            num_pairs += Rx_ij;

            POMAGMA_ASSERT(Lx_ij == Rx_ij,
                    "Lx,Rx disagree at " << i << "," << j
                    << ", Lx is " << Lx_ij << ", Rx is " << Rx_ij  );

            POMAGMA_ASSERT(sup_ij or not Lx_ij,
                    "Lx unsupported at " << i << "," << j );

            POMAGMA_ASSERT(sup_ij or not Rx_ij,
                    "Rx unsupported at " << i << "," << j );
        }
    }

    size_t true_size = count_pairs();
    POMAGMA_ASSERT(num_pairs == true_size,
            "incorrect number of pairs: "
            << num_pairs << " should be " << true_size);
}
Ejemplo n.º 15
0
void SymmetricFunction::unsafe_merge(const Ob dep) {
    POMAGMA_ASSERT5(support().contains(dep), "unsupported dep: " << dep);
    Ob rep = carrier().find(dep);
    POMAGMA_ASSERT5(support().contains(rep), "unsupported rep: " << rep);
    POMAGMA_ASSERT4(rep != dep, "self merge: " << dep << "," << rep);

    // (dep, dep) -> (rep, rep)
    if (defined(dep, dep)) {
        auto dep_iter = m_values.find(std::make_pair(dep, dep));
        Ob dep_val = dep_iter->second;
        m_values.erase(dep_iter);
        m_lines.Lx(dep, dep).zero();
        Ob& rep_val = m_values[std::make_pair(rep, rep)];
        if (carrier().set_or_merge(rep_val, dep_val)) {
            m_lines.Lx(rep, rep).one();
        }
    }

    // (dep, rhs) --> (rep, rhs) for rhs != dep
    rep = carrier().find(rep);
    for (auto iter = iter_lhs(dep); iter.ok(); iter.next()) {
        Ob rhs = *iter;
        auto dep_iter = m_values.find(make_sorted_pair(dep, rhs));
        Ob dep_val = dep_iter->second;
        m_values.erase(dep_iter);
        m_lines.Rx(dep, rhs).zero();
        Ob& rep_val = m_values[make_sorted_pair(rep, rhs)];
        if (carrier().set_or_merge(rep_val, dep_val)) {
            m_lines.Rx(rep, rhs).one();
        }
    }
    DenseSet dep_set(item_dim(), m_lines.Lx(dep));
    DenseSet rep_set(item_dim(), m_lines.Lx(rep));
    rep_set.merge(dep_set);

    // values must be updated in batch by update_values
}
Ejemplo n.º 16
0
// for growing
void base_bin_rel::move_from (const base_bin_rel & other)
{
    POMAGMA_DEBUG("Copying base_bin_rel");

    size_t min_item_dim = min(item_dim(), other.item_dim());
    size_t min_word_dim = min(word_dim(), other.word_dim());

    m_support.move_from(other.m_support);

    if (_symmetric()) {
        POMAGMA_ASSERT(other._symmetric(), "symmetry mismatch");
        for (size_t i = 1; i <= min_item_dim; ++i) {
            memcpy(Lx(i), other.Lx(i), sizeof(Word) * min_word_dim);
        }
    } else {
        POMAGMA_ASSERT(not other._symmetric(), "symmetry mismatch");
        for (size_t i = 1; i <= min_item_dim; ++i) {
            memcpy(Lx(i), other.Lx(i), sizeof(Word) * min_word_dim);
            memcpy(Rx(i), other.Rx(i), sizeof(Word) * min_word_dim);
        }
    }
}
Ejemplo n.º 17
0
void base_bin_rel::validate() const
{
    m_support.validate();

    // TODO validate Lx, Rx agree with support
    // (move code over from dense_bin_rel::validate()

    if (_symmetric()) {

        // check emptiness outside of support
        dense_set set(item_dim(), NULL);
        dense_set round_set(m_round_item_dim, NULL);
        for (oid_t i = 0; i < m_round_item_dim; ++i) {
            if (1 <= i and i <= item_dim()) {
                set.init(Lx(i));
                set.validate();
            } else {
                round_set.init(m_Lx_lines + m_round_word_dim * i);
                round_set.validate();
                POMAGMA_ASSERT(round_set.empty(),
                        "unsupported Lx(" << i << ") has " <<
                        round_set.count_items() << " items");
            }
        }

        // check for Lx/Rx agreement
        for (oid_t i = 1; i <= item_dim(); ++i) {
        for (oid_t j = i; j <= item_dim(); ++j) {
            POMAGMA_ASSERT(Lx(i, j) == Rx(i, j),
                    "Lx, Rx disagree at " << i << ',' << j);
        }}

    } else {

        // check emptiness outside of support
        dense_set set(item_dim(), NULL);
        dense_set round_set(m_round_item_dim, NULL);
        for (oid_t i = 0; i < m_round_item_dim; ++i) {
            if (1 <= i and i <= item_dim()) {
                set.init(Lx(i));
                set.validate();
                set.init(Rx(i));
                set.validate();
            } else {
                round_set.init(m_Lx_lines + m_round_word_dim * i);
                round_set.validate();
                POMAGMA_ASSERT(round_set.empty(),
                        "unsupported Lx(" << i << ") has " <<
                        round_set.count_items() << " items");
                round_set.init(m_Rx_lines + m_round_word_dim * i);
                round_set.validate();
                POMAGMA_ASSERT(round_set.empty(),
                        "unsupported Rx(" << i << ") has " <<
                        round_set.count_items() << " items");
            }
        }

        // check for Lx/Rx agreement
        for (oid_t i = 1; i <= item_dim(); ++i) {
        for (oid_t j = 1; j <= item_dim(); ++j) {
            POMAGMA_ASSERT(Lx(i, j) == Rx(i, j),
                    "Lx, Rx disagree at " << i << ',' << j);
        }}
    }
}
Ejemplo n.º 18
0
 DenseSet Rx_set (Ob rhs) const
 {
     return DenseSet(item_dim(), const_cast<std::atomic<Word> *>(Rx(rhs)));
 }
Ejemplo n.º 19
0
 // set wrappers
 DenseSet Lx_set (Ob lhs) const
 {
     return DenseSet(item_dim(), const_cast<std::atomic<Word> *>(Lx(lhs)));
 }
Ejemplo n.º 20
0
 bool_ref Rx (Ob lhs, Ob rhs)
 {
     POMAGMA_ASSERT_RANGE_(5, lhs, item_dim());
     return bool_ref::index(Rx(rhs), lhs);
 }
Ejemplo n.º 21
0
 bool_ref Lx (Ob lhs, Ob rhs)
 {
     POMAGMA_ASSERT_RANGE_(5, rhs, item_dim());
     return bool_ref::index(Lx(lhs), rhs);
 }
Ejemplo n.º 22
0
 std::atomic<Word> * Rx (Ob rhs)
 {
     POMAGMA_ASSERT_RANGE_(5, rhs, item_dim());
     return m_Rx_lines + (rhs * m_round_word_dim);
 }
Ejemplo n.º 23
0
 std::atomic<Word> * Lx (Ob lhs)
 {
     POMAGMA_ASSERT_RANGE_(5, lhs, item_dim());
     return m_Lx_lines + (lhs * m_round_word_dim);
 }
Ejemplo n.º 24
0
inline DenseSet::Iterator SymmetricFunction::iter_lhs(Ob lhs) const {
    POMAGMA_ASSERT5(support().contains(lhs), "unsupported lhs: " << lhs);
    return DenseSet::Iterator(item_dim(), m_lines.Lx(lhs));
}
Ejemplo n.º 25
0
Carrier::~Carrier ()
{
    destroy_blocks(m_reps, 1 + item_dim());
    free_blocks(m_reps);
}
Ejemplo n.º 26
0
inline DenseSet::Iterator BinaryRelation::iter_rhs(Ob rhs) const {
    POMAGMA_ASSERT5(support().contains(rhs), "unsupported rhs: " << rhs);
    return DenseSet::Iterator(item_dim(), m_lines.Rx(rhs));
}