Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在向量的每个struct元素中重置值的最快方法?_C++_Performance_Vector - Fatal编程技术网

C++ 在向量的每个struct元素中重置值的最快方法?

C++ 在向量的每个struct元素中重置值的最快方法?,c++,performance,vector,C++,Performance,Vector,非常类似,除了我有vector,而不是vector 如果我想为向量中的每个元素重置(或者设置为某个值)myType.myVar,最有效的方法是什么 现在我正在迭代: for(int i=0; i<myVec.size(); i++) myVec.at(i).myVar = 0; for(int i=0;i重置将需要遍历向量的每个元素,因此它至少需要O(n)复杂度。您当前的算法需要O(n) 在这种特殊情况下,您可以使用操作符[]而不是at(这可能会引发异常)。但我怀疑这是应用程序的瓶颈 在

非常类似,除了我有
vector
,而不是
vector

如果我想为向量中的每个元素重置(或者设置为某个值)
myType.myVar
,最有效的方法是什么

现在我正在迭代:

for(int i=0; i<myVec.size(); i++) myVec.at(i).myVar = 0;

for(int i=0;i重置将需要遍历向量的每个元素,因此它至少需要O(n)复杂度。您当前的算法需要O(n)

在这种特殊情况下,您可以使用
操作符[]
而不是
at
(这可能会引发异常)。但我怀疑这是应用程序的瓶颈

在此说明中,您可能应该使用:


但是,除非您想进入字节级并将一块内存设置为
0
,这不仅会让您头疼,而且在大多数情况下还会使您失去可移植性,否则这里没有什么可以改进的。

而不是下面的代码

for(int i=0; i<myVec.size(); i++) myVec.at(i).myVar = 0;

<代码> >(int i=0;i除了前面所说的,您应该考虑如果打开优化,编译器将可能执行循环展开,这将使循环本身更快。

也就是预增量<代码> ++i 很少有比后增量<代码> I++<代码>更少的指令。
解释

最快的方法之一是执行循环展开并打破传统
对造成大量现金溢出的
循环造成的速度限制。在您的情况下,由于这是一个运行时的事情,因此无法应用模板元编程,因此这是好的老达夫设备的一个变体e就行了

#include <iostream>
#include <vector>

using namespace std;

struct myStruct {
    int a;
    double b;
};

int main() 
{
    std::vector<myStruct> mV(20);

    double val(20);            // the new value you want to reset to
    int n = (mV.size()+7) / 8; // 8 is the size of the block unroll
    auto to = mV.begin();      // 

    switch(mV.size()%8)
    {
       case 0: do { (*to++).b = val;
       case 7:      (*to++).b = val;
       case 6:      (*to++).b = val;
       case 5:      (*to++).b = val;
       case 4:      (*to++).b = val;
       case 3:      (*to++).b = val;
       case 2:      (*to++).b = val;
       case 1:      (*to++).b = val;
        } while (--n>0);
    }

    // just printing to verify that the value is set
    for (auto i : mV) std::cout << i.b << std::endl;

    return 0;
}
#包括
#包括
使用名称空间std;
结构myStruct{
INTA;
双b;
};
int main()
{
std::向量mV(20);
double val(20);//要重置为的新值
int n=(mV.size()+7)/8;//8是块展开的大小
自动到=mV.begin();//
开关(mV.size()%8)
{
案例0:do{(*to++)。b=val;
案例7:(*到++).b=val;
案例6:(*到++).b=val;
案例5:(*到++).b=val;
案例4:(*到++).b=val;
案例3:(*到++).b=val;
案例2:(*到++).b=val;
案例1:(*到++).b=val;
}而(-n>0);
}
//只需打印以验证值是否已设置

对于(auto i:mV)std::cout请注意不要花太多时间考虑编译器将为您处理的优化细节

下面是我理解的OP的四个实现,以及使用GCC4.8和
--std=c++11-O3-S

声明:

#include <algorithm>
#include <vector>

struct T {
  int irrelevant;
  int relevant;
  double trailing;
};

当然
myVec.resize(10,{0})
是O(1)?我想知道是否有类似的方法,但在结构中保留其他变量的值。不过,谢谢!@OllieFord。不,调整大小的复杂性也是如此。好的,谢谢。我有一个后续问题,我是否可以将此合并到
std::sort
的“最后一次迭代”中,以重置排序所依据的值。请告知e我是应该把它作为一个新问题发布,还是编辑细节?@OllieFord,你说的“合并”是什么意思?用词不当。在我完成基于
myVal
的排序后,我想设置
myVal=0
。我能在上次运行
std::sort
时以某种方式做到这一点吗?很好!谢谢
。at()
-我只是在知道它“更安全”的情况下才使用它。现在我也知道了(至少部分)原因:)既然我们非常喜欢微优化,你也应该存储
myVec.size()
在变量中,而不是在每个循环中执行函数调用。哦,您可能也应该使用
++i
而不是
i++
。您知道。保存
std::size\t
整数的副本可能很有用。@OllieFord:at()被调用时,它会调用size()方法,然后检查索引是否小于大小。因此,在某种程度上,在访问每个元素时调用size()的开销非常小。运算符[]access只进行指针添加和返回。我想这会有所帮助。@tmp:它正在调用size()在每次迭代中显式地调用。在循环开始之前调用它一次并将其赋值给变量。根据这个答案,C++向量实际上是连续存储的。@粘土我读到一个答案,它们现在(不能找到)。-但这有更多的投票。将进行相应的编辑,谢谢。达夫的设备并不保证性能会更快。在许多情况下,已经观察到性能会降低。
#include <iostream>
#include <vector>

using namespace std;

struct myStruct {
    int a;
    double b;
};

int main() 
{
    std::vector<myStruct> mV(20);

    double val(20);            // the new value you want to reset to
    int n = (mV.size()+7) / 8; // 8 is the size of the block unroll
    auto to = mV.begin();      // 

    switch(mV.size()%8)
    {
       case 0: do { (*to++).b = val;
       case 7:      (*to++).b = val;
       case 6:      (*to++).b = val;
       case 5:      (*to++).b = val;
       case 4:      (*to++).b = val;
       case 3:      (*to++).b = val;
       case 2:      (*to++).b = val;
       case 1:      (*to++).b = val;
        } while (--n>0);
    }

    // just printing to verify that the value is set
    for (auto i : mV) std::cout << i.b << std::endl;

    return 0;
}
#include <algorithm>
#include <vector>

struct T {
  int irrelevant;
  int relevant;
  double trailing;
};
                                                        .cfi_startproc
                                                        movq    (%rdi), %rsi
void clear_relevant(std::vector<T>* vecp) {             movq    8(%rdi), %rcx
  for(unsigned i=0; i<vecp->size(); i++) {              xorl    %edx, %edx
    vecp->at(i).relevant = 0;                           xorl    %eax, %eax
  }                                                     subq    %rsi, %rcx
}                                                       sarq    $4, %rcx
                                                        testq   %rcx, %rcx
                                                        je      .L1
                                                        .p2align 4,,10
                                                        .p2align 3
                                                .L5:
void clear_relevant2(std::vector<T>* vecp) {            salq    $4, %rdx
  std::vector<T>& vec = *vecp;                          addl    $1, %eax
  auto s = vec.size();                                  movl    $0, 4(%rsi,%rdx)
  for (unsigned i = 0; i < s; ++i) {                    movl    %eax, %edx
    vec[i].relevant = 0;                                cmpq    %rcx, %rdx
  }                                                     jb      .L5
}                                               .L1:
                                                        rep ret
                                                        .cfi_endproc
                                                        .cfi_startproc
                                                        movq    8(%rdi), %rdx
                                                        movq    (%rdi), %rax
                                                        cmpq    %rax, %rdx
                                                        je      .L17
void clear_relevant3(std::vector<T>* vecp) {            .p2align 4,,10
  for (auto& p : *vecp) p.relevant = 0;                 .p2align 3
}                                               .L21:
                                                        movl    $0, 4(%rax)
                                                        addq    $16, %rax
                                                        cmpq    %rax, %rdx
                                                        jne     .L21
                                                .L17:
                                                        rep ret
                                                        .cfi_endproc


                                                        .cfi_startproc
                                                        movq    8(%rdi), %rdx
                                                        movq    (%rdi), %rax
                                                        cmpq    %rdx, %rax
void clear_relevant4(std::vector<T>* vecp) {            je      .L12
  std::for_each(vecp->begin(), vecp->end(),             .p2align 4,,10
                [](T& o){o.relevant=0;});               .p2align 3
}                                               .L16:
                                                        movl    $0, 4(%rax)
                                                        addq    $16, %rax
                                                        cmpq    %rax, %rdx
                                                        jne     .L16
                                                .L12:
                                                        rep ret
                                                        .cfi_endproc