是否有类似 C++ 的限制关键字之类的东西?指示 _iterators_ 没有别名

发布于 2024-10-16 23:13:29 字数 190 浏览 0 评论 0原文

g++ 确实实现了指针的 __restrict__ ,但我找不到有关迭代器的任何信息。我的总体意图是鼓励编译器对 stl 循环进行矢量化。

编辑:

即使编译器无法矢量化,__restrict__关键字也应该能够告诉编译器循环内不需要不必要的重新加载。

g++ does implement __restrict__ for pointers, but I could not find anything about iterators. My overall intent is to encourage the compiler to vectorize stl loops.

Edit:

Even if the compiler is unable to vectorize, the __restrict__ keyword should be able to tell the compiler that no unnecessary reloads are necessary inside a loop.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伴随着你 2024-10-23 23:13:29

我不知道你直接问题的答案。但是,编译器只能对 std::vector 的循环进行矢量化,因为它是唯一具有连续存储的容器(我认为),并且连续存储位置之间没有依赖关系(与例如std::list)。但我不知道如何让它这样做。

更新

经过一些实验(可能与总体目标相关,也可能不相关),我发现在 ICC 中,以下内容矢量化:

typedef std::vector<float> V;

V vec(4096);

for (V::iterator it = vec.begin(); it != vec.end(); ++it)
{
    *it *= *it;
}

而以下内容

V vec(4096);

V::iterator it2 = vec.end();
for (V::iterator it = vec.begin(); it != it2; ++it)
{
    *it *= *it;
}

则 :显然,问题不在于迭代器,而在于循环构造内对 vec.end() 的调用,这显然无法被分解出来,尽管很明显循环体不会影响向量边界。

在 GCC 中,我无法对任何内容进行矢量化。这并不奇怪,因为 GCC 在发现 SSE 机会方面比 ICC 差很多。

I don't know the answer to your direct question. However, the compiler would only ever be able to vectorize a loop for std::vector, as it's the only container (I think) that has contiguous storage, and no dependencies between successive storage locations (unlike e.g. std::list). I don't know how to make it do so, though.

Update

After some experimentation (which may or may not be relevant to the overall goal), I discovered that in ICC, the following does not vectorise:

typedef std::vector<float> V;

V vec(4096);

for (V::iterator it = vec.begin(); it != vec.end(); ++it)
{
    *it *= *it;
}

whereas the following does:

V vec(4096);

V::iterator it2 = vec.end();
for (V::iterator it = vec.begin(); it != it2; ++it)
{
    *it *= *it;
}

So apparently, the problem is not so much iterators, but the call to vec.end() inside the loop construct, which apparently cannot be factored out, even though it's clear that the loop body doesn't affect the vector bounds.

In GCC, I couldn't get anything to vectorise. This isn't surprising, because GCC is much worse than ICC at spotting SSE opportunities.

撩起发的微风 2024-10-23 23:13:29

采用这个 C++20 解决方案:

#pragma once
#include <cstddef>
#include <memory>
#include <iterator>
#include <type_traits>
#include <concepts>

template<typename Iterator>
concept restrict_it_concept = requires() { { *Iterator() }; } || requires() { { (Iterator())[(std::ptrdiff_t)1] }; };

template<restrict_it_concept Iterator>
struct restrict_it final
{
    using value_type = std::remove_reference_t<std::conditional_t<requires() { { *Iterator() }; }, decltype(*Iterator()), decltype((Iterator())[(ptrdiff_t)1])>>;
    constexpr restrict_it() noexcept
        requires requires() { { Iterator() }; };
    constexpr restrict_it( Iterator it ) noexcept
        requires requires( Iterator it ) { { Iterator( it ) }; };
    constexpr restrict_it( restrict_it const &other ) noexcept
        requires requires( Iterator it ) { { Iterator( it ) }; };
    constexpr restrict_it &operator =( Iterator it ) noexcept
        requires requires( Iterator it ) { { it = it }; };
    constexpr restrict_it &operator =( restrict_it const &other ) noexcept
        requires requires( Iterator it ) { { it = it }; };
    constexpr bool operator <( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it < it } -> std::convertible_to<bool>; };
    constexpr bool operator <=( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it <= it } -> std::convertible_to<bool>; };
    constexpr bool operator >( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it > it } -> std::convertible_to<bool>; };
    constexpr bool operator >=( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it >= it } -> std::convertible_to<bool>; };
    constexpr bool operator ==( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it == it } -> std::convertible_to<bool>; };
    constexpr bool operator !=( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it != it } -> std::convertible_to<bool>; };
    constexpr std::ptrdiff_t operator -( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it - it } -> std::convertible_to<std::ptrdiff_t>; };
    constexpr restrict_it &operator ++() noexcept
        requires requires( Iterator it ) { { ++it }; };
    constexpr restrict_it &operator --() noexcept
        requires requires( Iterator it ) { { --it }; };
    constexpr restrict_it operator ++( int ) const noexcept
        requires requires( Iterator it ) { { it++ } -> std::convertible_to<Iterator>; };
    constexpr restrict_it operator --( int ) const noexcept
        requires requires( Iterator it ) { { it-- } -> std::convertible_to<Iterator>; };
    constexpr restrict_it operator +( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it + offset } -> std::convertible_to<Iterator>; };
    friend constexpr restrict_it operator +( std::ptrdiff_t offset, restrict_it it ) noexcept
        requires requires( std::ptrdiff_t offset, Iterator it ) { { offset + it } -> std::convertible_to<Iterator>; }
    {
        return restrict_it( offset + it.m_it );
    }
    constexpr restrict_it operator -( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it - offset } -> std::convertible_to<Iterator>; };
    constexpr value_type &__restrict operator *() const noexcept
        requires requires( Iterator it ) { { *it } -> std::convertible_to<value_type &>; };
    constexpr value_type &__restrict operator []( std::ptrdiff_t index ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t index ) { { it[index] } -> std::convertible_to<value_type &>; };
    constexpr value_type *__restrict operator ->() const noexcept
        requires requires( Iterator it ) { { it.operator ->() } -> std::convertible_to<value_type *>; };
    constexpr restrict_it &operator +=( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it += offset }; };
    constexpr restrict_it &operator -=( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it -= offset }; };
private:
    Iterator m_it;
};

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator>::restrict_it() noexcept
    requires requires() { { Iterator() }; }
    : m_it()
{
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator>::restrict_it( Iterator it ) noexcept
    requires requires( Iterator it ) { { Iterator( it ) }; }
    : m_it( it )
{
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator>::restrict_it( restrict_it const &other ) noexcept
    requires requires( Iterator it ) { { Iterator( it ) }; }
    : m_it( other.m_it )
{
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator =( Iterator it ) noexcept
    requires requires( Iterator it ) { { it = it }; }
{
    m_it = it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator =( restrict_it const &other ) noexcept
    requires requires( Iterator it ) { { it = it }; }
{
    m_it = other.m_it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator <( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it < it } -> std::convertible_to<bool>; }
{
    return m_it < other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator <=( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it <= it } -> std::convertible_to<bool>; }
{
    return m_it <= other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator >( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it > it } -> std::convertible_to<bool>; }
{
    return m_it > other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator >=( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it >= it } -> std::convertible_to<bool>; }
{
    return m_it >= other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator ==( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it == it } -> std::convertible_to<bool>; }
{
    return m_it == other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator !=( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it != it } -> std::convertible_to<bool>; }
{
    return m_it != other.m_it;
}

template<restrict_it_concept Iterator>
constexpr std::ptrdiff_t restrict_it<Iterator>::operator -( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it - it } -> std::convertible_to<std::ptrdiff_t>; }
{
    return m_it - other.m_it;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator ++() noexcept
    requires requires( Iterator it ) { { ++it }; }
{
    ++m_it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator --() noexcept
    requires requires( Iterator it ) { { --it }; }
{
    --m_it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator ++( int ) const noexcept
    requires requires( Iterator it ) { { it++ } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it++ );
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator --( int ) const noexcept
    requires requires( Iterator it ) { { it-- } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it-- );
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator +( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it + offset } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it + offset );
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator -( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it - offset } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it - offset );
}

template<restrict_it_concept Iterator>
constexpr typename restrict_it<Iterator>::value_type &__restrict restrict_it<Iterator>::operator *() const noexcept
    requires requires( Iterator it ) { { *it } -> std::convertible_to<value_type &>; }
{
    return *m_it;
}

template<restrict_it_concept Iterator>
constexpr typename restrict_it<Iterator>::value_type &__restrict restrict_it<Iterator>::operator []( std::ptrdiff_t index ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t index ) { { it[index] } -> std::convertible_to<value_type &>; }
{
    return m_it[index];
}

template<restrict_it_concept Iterator>
constexpr typename restrict_it<Iterator>::value_type *__restrict restrict_it<Iterator>::operator ->() const noexcept
    requires requires( Iterator it ) { { it.operator ->() } -> std::convertible_to<value_type *>; }
{
    return m_it.operator ->();
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator +=( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it += offset }; }
{
    m_it += offset;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator -=( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it -= offset }; }
{
    m_it -= offset;
    return *this;
}

#if !defined(NDEBUG)
#include <vector>
template<>
struct restrict_it<typename std::vector<char>::const_iterator>;
#endif

使用它,您可以简单地编写:

restrict_it it( vec.cbegin() );

适用于任何容器。

Take this C++20-solution:

#pragma once
#include <cstddef>
#include <memory>
#include <iterator>
#include <type_traits>
#include <concepts>

template<typename Iterator>
concept restrict_it_concept = requires() { { *Iterator() }; } || requires() { { (Iterator())[(std::ptrdiff_t)1] }; };

template<restrict_it_concept Iterator>
struct restrict_it final
{
    using value_type = std::remove_reference_t<std::conditional_t<requires() { { *Iterator() }; }, decltype(*Iterator()), decltype((Iterator())[(ptrdiff_t)1])>>;
    constexpr restrict_it() noexcept
        requires requires() { { Iterator() }; };
    constexpr restrict_it( Iterator it ) noexcept
        requires requires( Iterator it ) { { Iterator( it ) }; };
    constexpr restrict_it( restrict_it const &other ) noexcept
        requires requires( Iterator it ) { { Iterator( it ) }; };
    constexpr restrict_it &operator =( Iterator it ) noexcept
        requires requires( Iterator it ) { { it = it }; };
    constexpr restrict_it &operator =( restrict_it const &other ) noexcept
        requires requires( Iterator it ) { { it = it }; };
    constexpr bool operator <( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it < it } -> std::convertible_to<bool>; };
    constexpr bool operator <=( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it <= it } -> std::convertible_to<bool>; };
    constexpr bool operator >( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it > it } -> std::convertible_to<bool>; };
    constexpr bool operator >=( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it >= it } -> std::convertible_to<bool>; };
    constexpr bool operator ==( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it == it } -> std::convertible_to<bool>; };
    constexpr bool operator !=( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it != it } -> std::convertible_to<bool>; };
    constexpr std::ptrdiff_t operator -( restrict_it const &other ) const noexcept
        requires requires( Iterator it ) { { it - it } -> std::convertible_to<std::ptrdiff_t>; };
    constexpr restrict_it &operator ++() noexcept
        requires requires( Iterator it ) { { ++it }; };
    constexpr restrict_it &operator --() noexcept
        requires requires( Iterator it ) { { --it }; };
    constexpr restrict_it operator ++( int ) const noexcept
        requires requires( Iterator it ) { { it++ } -> std::convertible_to<Iterator>; };
    constexpr restrict_it operator --( int ) const noexcept
        requires requires( Iterator it ) { { it-- } -> std::convertible_to<Iterator>; };
    constexpr restrict_it operator +( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it + offset } -> std::convertible_to<Iterator>; };
    friend constexpr restrict_it operator +( std::ptrdiff_t offset, restrict_it it ) noexcept
        requires requires( std::ptrdiff_t offset, Iterator it ) { { offset + it } -> std::convertible_to<Iterator>; }
    {
        return restrict_it( offset + it.m_it );
    }
    constexpr restrict_it operator -( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it - offset } -> std::convertible_to<Iterator>; };
    constexpr value_type &__restrict operator *() const noexcept
        requires requires( Iterator it ) { { *it } -> std::convertible_to<value_type &>; };
    constexpr value_type &__restrict operator []( std::ptrdiff_t index ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t index ) { { it[index] } -> std::convertible_to<value_type &>; };
    constexpr value_type *__restrict operator ->() const noexcept
        requires requires( Iterator it ) { { it.operator ->() } -> std::convertible_to<value_type *>; };
    constexpr restrict_it &operator +=( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it += offset }; };
    constexpr restrict_it &operator -=( std::ptrdiff_t offset ) const noexcept
        requires requires( Iterator it, std::ptrdiff_t offset ) { { it -= offset }; };
private:
    Iterator m_it;
};

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator>::restrict_it() noexcept
    requires requires() { { Iterator() }; }
    : m_it()
{
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator>::restrict_it( Iterator it ) noexcept
    requires requires( Iterator it ) { { Iterator( it ) }; }
    : m_it( it )
{
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator>::restrict_it( restrict_it const &other ) noexcept
    requires requires( Iterator it ) { { Iterator( it ) }; }
    : m_it( other.m_it )
{
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator =( Iterator it ) noexcept
    requires requires( Iterator it ) { { it = it }; }
{
    m_it = it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator =( restrict_it const &other ) noexcept
    requires requires( Iterator it ) { { it = it }; }
{
    m_it = other.m_it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator <( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it < it } -> std::convertible_to<bool>; }
{
    return m_it < other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator <=( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it <= it } -> std::convertible_to<bool>; }
{
    return m_it <= other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator >( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it > it } -> std::convertible_to<bool>; }
{
    return m_it > other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator >=( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it >= it } -> std::convertible_to<bool>; }
{
    return m_it >= other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator ==( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it == it } -> std::convertible_to<bool>; }
{
    return m_it == other.m_it;
}

template<restrict_it_concept Iterator>
constexpr bool restrict_it<Iterator>::operator !=( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it != it } -> std::convertible_to<bool>; }
{
    return m_it != other.m_it;
}

template<restrict_it_concept Iterator>
constexpr std::ptrdiff_t restrict_it<Iterator>::operator -( restrict_it const &other ) const noexcept
    requires requires( Iterator it ) { { it - it } -> std::convertible_to<std::ptrdiff_t>; }
{
    return m_it - other.m_it;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator ++() noexcept
    requires requires( Iterator it ) { { ++it }; }
{
    ++m_it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator --() noexcept
    requires requires( Iterator it ) { { --it }; }
{
    --m_it;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator ++( int ) const noexcept
    requires requires( Iterator it ) { { it++ } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it++ );
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator --( int ) const noexcept
    requires requires( Iterator it ) { { it-- } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it-- );
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator +( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it + offset } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it + offset );
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> restrict_it<Iterator>::operator -( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it - offset } -> std::convertible_to<Iterator>; }
{
    return restrict_it( m_it - offset );
}

template<restrict_it_concept Iterator>
constexpr typename restrict_it<Iterator>::value_type &__restrict restrict_it<Iterator>::operator *() const noexcept
    requires requires( Iterator it ) { { *it } -> std::convertible_to<value_type &>; }
{
    return *m_it;
}

template<restrict_it_concept Iterator>
constexpr typename restrict_it<Iterator>::value_type &__restrict restrict_it<Iterator>::operator []( std::ptrdiff_t index ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t index ) { { it[index] } -> std::convertible_to<value_type &>; }
{
    return m_it[index];
}

template<restrict_it_concept Iterator>
constexpr typename restrict_it<Iterator>::value_type *__restrict restrict_it<Iterator>::operator ->() const noexcept
    requires requires( Iterator it ) { { it.operator ->() } -> std::convertible_to<value_type *>; }
{
    return m_it.operator ->();
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator +=( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it += offset }; }
{
    m_it += offset;
    return *this;
}

template<restrict_it_concept Iterator>
constexpr restrict_it<Iterator> &restrict_it<Iterator>::operator -=( std::ptrdiff_t offset ) const noexcept
    requires requires( Iterator it, std::ptrdiff_t offset ) { { it -= offset }; }
{
    m_it -= offset;
    return *this;
}

#if !defined(NDEBUG)
#include <vector>
template<>
struct restrict_it<typename std::vector<char>::const_iterator>;
#endif

With that you could simply write:

restrict_it it( vec.cbegin() );

Works with any container.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文