Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.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++代码之后,25%的(时间)的时间花在调用::运算符[]/COD>。没错,我的代码将所有时间都花在vectors(还有一些vectors)上读写,但我还是想知道,与C风格数组相比,操作符[]是否应该有一些显著的开销_C++_Stl_Vector - Fatal编程技术网

向量::运算符[]开销 显然,在剖析我的(科学计算)C++代码之后,25%的(时间)的时间花在调用::运算符[]/COD>。没错,我的代码将所有时间都花在vectors(还有一些vectors)上读写,但我还是想知道,与C风格数组相比,操作符[]是否应该有一些显著的开销

向量::运算符[]开销 显然,在剖析我的(科学计算)C++代码之后,25%的(时间)的时间花在调用::运算符[]/COD>。没错,我的代码将所有时间都花在vectors(还有一些vectors)上读写,但我还是想知道,与C风格数组相比,操作符[]是否应该有一些显著的开销,c++,stl,vector,C++,Stl,Vector,(我已经看到了另一个相关的问题,但是关于[]和at()——但显然连[]对我来说都太慢了?!) 谢谢, 安东尼 (编辑:仅供参考:在Ubuntu上使用g++-O3版本4.5.2)在现代编译器中,在发布模式下,启用优化后,与原始指针相比,使用操作符[]没有开销:调用完全内联,只解析为指针访问 我猜您是在某种程度上复制赋值中的返回值,这导致指令中实际花费了25%的时间。[与float和int无关] 或者,代码的其余部分速度非常快。纯数组访问是(几乎)直接内存读取,而运算符[]是向量的成员方法 如果正确

(我已经看到了另一个相关的问题,但是关于
[]
at()
——但显然连
[]
对我来说都太慢了?!)

谢谢, 安东尼


(编辑:仅供参考:在Ubuntu上使用g++-O3版本4.5.2)

在现代编译器中,在发布模式下,启用优化后,与原始指针相比,使用
操作符[]
没有开销:调用完全内联,只解析为指针访问

我猜您是在某种程度上复制赋值中的返回值,这导致指令中实际花费了25%的时间。[与
float
int
无关]

或者,代码的其余部分速度非常快。

纯数组访问是(几乎)直接内存读取,而运算符[]是向量的成员方法


如果正确内联,则应该是相同的,否则,对于计算密集型工作来说,开销非常大。

是的,会有一些开销,因为通常
向量将包含指向动态分配数组的指针,而数组正好“在那里”。这意味着在数组上使用
[]
时,
vector::operator[]
中通常会有额外的内存解引用。(请注意,如果您有一个指向数组的指针,这通常不比
向量
好多少)

如果您通过同一段代码中的同一
向量
或指针执行多个访问,而不导致向量可能需要重新分配,那么此额外的解引用成本可能会在多个访问中分摊,并且可以忽略不计

例如


请注意指针和向量版本如何产生完全相同的代码,只有数组版本“获胜”。

一般来说,应该没有显著差异。差异可以 然而,在实践中,由于各种原因,这取决于 编译器优化特定的代码位。一个重要的可能性 区别:您正在分析,这意味着您正在执行 插入指令的代码。我不知道你用的是什么分析器,但它是 编译器经常出于各种原因关闭内联 检测以进行分析。你确定不是这样吗 在这里,这是人为地导致指数化出现
与内联的情况相比,需要花费更多的时间。

std::vector::operator[]
应该相当有效,但是编译器必须是偏执的,并且对于对函数的每次调用,它必须假设向量可能已在内存中的其他位置移动

例如,在本代码中

for (int i=0,n=v.size(); i<n; i++)
{
    total += v[i] + foo();
}
使用这种方法,可以保存一个内存查找操作(
vptr
很可能会在整个循环的寄存器中结束)

效率低下的另一个原因可能是缓存垃圾。要想知道这是否是问题所在,一个简单的技巧就是通过一些不均匀的元素来分配向量

原因是,由于高速缓存的工作原理,如果您有许多向量,例如4096个元素,那么所有这些向量的地址中将恰好具有相同的低阶位,并且您可能会因为高速缓存线失效而失去很多速度。 例如,我的电脑上的这个循环

std::vector<double> v1(n), v2(n), v3(n), v4(n), v5(n);
for (int i=0; i<1000000; i++)
    for (int j=0; j<1000; j++)
    {
        v1[j] = v2[j] + v3[j];
        v2[j] = v3[j] + v4[j];
        v3[j] = v4[j] + v5[j];
        v4[j] = v5[j] + v1[j];
        v5[j] = v1[j] + v2[j];
    }
标准::向量v1(n)、v2(n)、v3(n)、v4(n)、v5(n);
对于(int i=0;我希望您确保打开优化:)了解编译器和操作系统也很好。我真诚地怀疑这与调用
[]
的任何开销有关,这可能纯粹是因为您访问向量的次数减少了。可能需要调整您的算法以减少需要访问的次数?您的STL实现是什么?你在用什么来分析?通常情况下,运算符[]在优化构建中订阅C数组时几乎没有明显的开销。测量的行为可能会抑制优化(取决于它是如何完成的),或者你可能会使用STL进行激进的错误检查(例如,微软在某些配置/版本中的STL)。向量有多大?顺序或随机访问?相对较小的向量(最多几千个元素,通常只有几十个),大部分是随机访问。当然,这是假设您没有使用添加运行时检查的一些深奥的标准库实现。我认为OP提到了一些关于
float
int
,怀疑副本可能是这里的问题(?)+1关于插入指令的代码的注释。对于快速代码,唯一可行的选择是被动统计分析器(例如oprofile)。任何形式的工具都会使测量变得毫无意义。也许这就是问题所在。
for (int i=0,n=v.size(); i<n; i++)
{
    total += v[i] + foo();
}
double *vptr = &v[0]; // Address of first element
for (int i=0,n=v.size(); i<n; i++)
{
    total += vptr[i] + foo();
}
std::vector<double> v1(n), v2(n), v3(n), v4(n), v5(n);
for (int i=0; i<1000000; i++)
    for (int j=0; j<1000; j++)
    {
        v1[j] = v2[j] + v3[j];
        v2[j] = v3[j] + v4[j];
        v3[j] = v4[j] + v5[j];
        v4[j] = v5[j] + v1[j];
        v5[j] = v1[j] + v2[j];
    }