- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设我有一个使用结构数组 (AoS) 内存布局的大代码。我想用 C++ 构建一个零成本的抽象,它允许我以尽可能少的重构工作在 AoS 和 SoA 之间切换。
例如,使用具有访问成员函数的类
struct Item{
auto& myDouble(){ return mDouble; }
auto& myChar(){ return mChar; }
auto& myString(){ return mString; }
private:
double mDouble;
char mChar;
std::string mString;
};
std::vector<Item> vec_(1000);
for (auto& i : vec_)
i.myDouble()=5.;
MyContainer<Item, SoA> vec_(1000)
for (auto& i : vec_)
i.myDouble()=5.;
最佳答案
我实现了一个通用的解决方案,我将在下面解释它(这将是一个很长的帖子)。这当然不是唯一可能的答案,收集反馈会很棒。我把这个解决方案的完整代码放在这里 https://github.com/crosetto/SoAvsAoS
我们创建了两个助手类,它们根据标签模板参数将容器类型生成为元组 vector 或 vector 元组。我们称这个类为 DataLayoutPolicy,我们将使用它,例如通过这种方式:
DataLayoutPolicy<std::vector, SoA, char, double, std::string>
enum class DataLayout { SoA, //structure of arrays
AoS //array of structures
};
template <template <typename...> class Container, DataLayout TDataLayout, typename TItem>
struct DataLayoutPolicy;
template <template <typename...> class Container, template<typename...> class TItem, typename... Types>
struct DataLayoutPolicy<Container, DataLayout::AoS, TItem<Types...>> {
using type = Container<TItem<Types...>>;
using value_type = TItem<Types...>&;
constexpr static value_type get( type& c_, std::size_t position_ ){ return value_type(*static_cast<TItem<Types...>*>(&c_[ position_ ])); }
constexpr static void resize( type& c_, std::size_t size_ ) { c_.resize( size_ ); }
template <typename TValue>
constexpr static void push_back( type& c_, TValue&& val_ ){ c_.push_back( val_ ); }
static constexpr std::size_t size(type& c_){ return c_.size(); }
};
template <typename T>
struct ref_wrap : public std::reference_wrapper<T>{
operator T&() const noexcept { return this->get(); }
ref_wrap(T& other_) : std::reference_wrapper<T>(other_){}
void operator =(T && other_) {this->get()=other_;}
};
template <template <typename...> class Container, template<typename...> class TItem, typename... Types>
struct DataLayoutPolicy<Container, DataLayout::SoA, TItem<Types...>> {
using type = std::tuple<Container<Types>...>;
using value_type = TItem<ref_wrap<Types>...>;
constexpr static value_type get( type& c_, std::size_t position_ )
{
return doGet( c_, position_, std::make_integer_sequence<unsigned, sizeof...( Types )>() ); // unrolling parameter pack
}
constexpr static void resize( type& c_, std::size_t size_ ) {
doResize( c_, size_, std::make_integer_sequence<unsigned, sizeof...( Types )>() ); // unrolling parameter pack
}
template <typename TValue>
constexpr static void push_back( type& c_, TValue&& val_ ){
doPushBack( c_, std::forward<TValue>(val_), std::make_integer_sequence<unsigned, sizeof...( Types )>() ); // unrolling parameter pack
}
static constexpr std::size_t size(type& c_){ return std::get<0>( c_ ).size(); }
private:
template <unsigned... Ids>
constexpr static auto doGet( type& c_, std::size_t position_, std::integer_sequence<unsigned, Ids...> )
{
return value_type{ ref_wrap( std::get<Ids>( c_ )[ position_ ] )... }; // guaranteed copy elision
}
template <unsigned... Ids>
constexpr static void doResize( type& c_, unsigned size_, std::integer_sequence<unsigned, Ids...> )
{
( std::get<Ids>( c_ ).resize( size_ ), ... ); //fold expressions
}
template <typename TValue, unsigned... Ids>
constexpr static void doPushBack( type& c_, TValue&& val_, std::integer_sequence<unsigned, Ids...> )
{
( std::get<Ids>( c_ ).push_back( std::get<Ids>( std::forward<TValue>( val_ ) ) ), ... ); // fold expressions
}
};
template <template <typename T> class TContainer, DataLayout TDataLayout, typename TItem>
using policy_t = DataLayoutPolicy<TContainer, TDataLayout, TItem>;
template <template <typename ValueType> class TContainer, DataLayout TDataLayout, typename TItem>
struct BaseContainer
{
/*member functions like puhs_back, resize,...*/
value_type operator[]( std::size_t position_ )
{
return policy_t::get( mValues, position_ );
}
iterator begin() { return iterator( this, 0 ); }
iterator end() { return iterator( this, size() ); }
private:
typename policy_t::type mValues;
};
template <typename TContainer>
class Iterator
{
private:
using container_t = TContainer;
public:
/* ... usual iterator member functions and type definitions ...*/
template<typename TTContainer>
Iterator( TTContainer* container_, std::size_t position_ = 0 ):
mContainer( container_ )
, mIterPosition( position_ )
{
}
value_type operator*() {
return (*mContainer)[ mIterPosition ];
}
private:
container_t* mContainer = nullptr;
std::size_t mIterPosition = std::numeric_limits<std::size_t>::infinity();
};
template<typename ... T>
struct Item : public std::tuple<T ...>{
using std::tuple<T...>::tuple;
auto & myDouble(){return std::get<0>(*this);}
auto & myChar() {return std::get<1>(*this);}
auto & myString(){return std::get<2>(*this);}
};
template<typename T>
using MyVector = std::vector<T, std::allocator<T>>;
int main(int argc, char** argv){
using container_t = BaseContainer<MyVector, DataLayout::SoA, Item<double, char, std::string, Pad> >;
container_t container_(1000);
for(auto&& i : container_){
i.myDouble()=static_cast<double>(argc);
}
> clang++ -std=c++1z -O3 -g main.cpp -o test
> gdb test
(gdb) break main.cpp : 10 # set breakpoint inside the loop
(gdb) run # execute until the breakpoint
(gdb) layout split # show assembly and source code in 2 separate frames
(gdb) stepi # execute one instruction
0x400b00 <main(int, char**)+192> movsd %xmm0,(%rsi)
0x400b04 <main(int, char**)+196> add $0x610,%rsi
0x400b0b <main(int, char**)+203> add $0xffffffffffffffff,%rcx
0x400b0f <main(int, char**)+207> jne 0x400b00 <main(int, char**)+192>
0x400b60 <main(int, char**)+224> movups %xmm1,(%rdi,%rsi,8)
0x400b64 <main(int, char**)+228> movups %xmm1,0x10(%rdi,%rsi,8)
0x400b69 <main(int, char**)+233> movups %xmm1,0x20(%rdi,%rsi,8)
0x400b6e <main(int, char**)+238> movups %xmm1,0x30(%rdi,%rsi,8)
0x400b73 <main(int, char**)+243> movups %xmm1,0x40(%rdi,%rsi,8)
0x400b78 <main(int, char**)+248> movups %xmm1,0x50(%rdi,%rsi,8)
0x400b7d <main(int, char**)+253> movups %xmm1,0x60(%rdi,%rsi,8)
0x400b82 <main(int, char**)+258> movups %xmm1,0x70(%rdi,%rsi,8)
0x400b87 <main(int, char**)+263> movups %xmm1,0x80(%rdi,%rsi,8)
0x400b8f <main(int, char**)+271> movups %xmm1,0x90(%rdi,%rsi,8)
0x400b97 <main(int, char**)+279> movups %xmm1,0xa0(%rdi,%rsi,8)
0x400b9f <main(int, char**)+287> movups %xmm1,0xb0(%rdi,%rsi,8)
0x400ba7 <main(int, char**)+295> movups %xmm1,0xc0(%rdi,%rsi,8)
0x400baf <main(int, char**)+303> movups %xmm1,0xd0(%rdi,%rsi,8)
0x400bb7 <main(int, char**)+311> movups %xmm1,0xe0(%rdi,%rsi,8)
0x400bbf <main(int, char**)+319> movups %xmm1,0xf0(%rdi,%rsi,8)
0x400bc7 <main(int, char**)+327> add $0x20,%rsi
0x400bcb <main(int, char**)+331> add $0x8,%rbx
0x400bcf <main(int, char**)+335> jne 0x400b60 <main(int, char**)+224>
关于SoA/AoS 内存布局的 C++ 零成本抽象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50574639/
我正在尝试将 iOS 设备名称连同 deviceToken 一起发送到我在 didRegisterForRemoteNotificationsWithDeviceToken 中的服务器。我的设备中有一
那些在人工智能(或同等)领域工作过或工作过的人应该对 AO* 算法非常了解。 很明显它是一个通用算法。 你们中有人遇到过 AO* 算法的任何实际应用吗?你们中的一些人可能已经使用过它。 因此,如果您能
我注意到在实现搜索算法时会使用一些数据结构。比如我们用queue来实现BFS,用stack来实现DFS,用min-heap来实现A*算法。在这些情况下,我们不需要显式构造搜索树。 但是我找不到一个简单
JavaScript的执行过程 前言 编写一段JavaScript代码,它是如何执行的呢?简单来说,JS引擎在执行JavaScript代码的过程中需要先解析再执行。那么在解析阶段JS引擎又会进行哪些操
首次加载此页面时,AOS 运行良好。每个“白色方块”动画同时触发并且所有 6 个方块都可见。但是,我注意到,当我将浏览器调整为较小的大小,然后将其重新调整为较大的大小时,AOS 与我设置的媒体查询相结
通常在 HTML 文件中我像这样使用 AOS 我尝试以不同的方式在 CSS 文件中使用 AOS 和伪元素,但我没有这样做。你知道我该怎么做吗?感谢您的帮助 &::before {
我正在使用 AOS 库(css 和 js)它帮助我创建每次用户向下滚动页面时触发的动画。我有一个问题,我的页面的顶部元素只运行一次,因为 AOS 只在向下滚动时触发它。我希望我所有的动画运行 evry
我是 GatsbyJS 和 ReactJS 的新手,在构建项目时遇到问题。问题是每当我在其中构建带有 AOS 的项目时,它都会显示错误窗口未定义。当我在开发模式下运行时完全没问题。 这是我的代码: 我
在使用 OpenApi 规范的 swagger 文档中,您可以将 schema 包装在参数中以包含 application/json 的内容: parameters: - in: query
我在Android OS v4.x(尤其是4.0.3)上遇到一个问题,即在滚动时更改ListView的数据-发生崩溃是因为我试图更改的不是主UI线程的数据,这是不正确的: E/AndroidR
我在 PostgreSQL 中有这个选择: SELECT "field_1", "field_2","field_3", MIN(COALESCE(NULLIF("field_4",'') ,'TBD
我正在使用 AOS 库制作动画。当我使用动画向左和向右滑动时,页面的宽度变得比主体宽度更宽,使整个页面看起来很奇怪。我无法在网上找到任何解决方案,我想出的唯一解决方案是,如果我给应用动画的元素以 px
这又是一个极其简单的问题。只是我,还是 AOS.js 只适用于 div? 因为在下面的链接中,我在 h1 上尝试它,但它不起作用。我在 div 上试了一下,它起作用了。这是一个更大问题的一部分,该元素
假设我有一个使用结构数组 (AoS) 内存布局的大代码。我想用 C++ 构建一个零成本的抽象,它允许我以尽可能少的重构工作在 AoS 和 SoA 之间切换。 例如,使用具有访问成员函数的类 stru
我有一个窗口弹出类,它在 aos 2.x(如 2.2.2、2.3.5 等)中运行良好,但在 aos 4.x 中崩溃。导致崩溃的代码如下: public void dismissPopup(){
我正在尝试添加属性以通过 javascript 启动 AOS 动画,但它无法正常工作。现在,通过js添加属性,当动画启动时,不是显示元素,而是隐藏它。我想可能是因为元素先渲染,js在添加AOS属性后才
我正在尝试将 Michalsnik 的 Animate On Scroll 插件实现到我的 WordPress 网站中。但是,当我按照指示使用“data-aos”制作以下 div 时,该元素变成空白而
我正在使用fullpagejs和 AOS使一些 div 在滚动时从页面底部弹出(或者至少这是我想要实现的)。 不幸的是,它不起作用。 是的,我已阅读 FAQ全页的部分,是的,scrollbar 设置为
我使用FullPage用于在部分之间进行动画滚动。 我想让项目显示为 aos.js但是当 fullPage.js 工作时 aos 不起作用。 最佳答案 详情请参阅 the fullPage.js FA
我将 AOS(滚动动画)库与 vue 一起使用。 AOS提供自定义JS事件:document.addEventListener('aos:in', ({ detail }) => { console.
我是一名优秀的程序员,十分优秀!