std :: fill不会变成POD类型的memset

时间:2011-02-22 05:01:56

标签: c++

我期待连续容器上的std :: fill,比如std :: vector,会自动编译为memset的调用。但是,当我尝试以下代码时

#include <vector>
#include <algorithm>
#include <numeric>

using namespace std;

int main()
{
    vector<double> vec(300000);

    fill(vec.begin(),vec.end(),0.0);

    memset(&vec[0],0,vec.size()*sizeof(double));
}

gcc将第一个std :: fill编译成一个简单的循环。但我认为可以通过SSE或其他高级矢量化代码来完成。请给我一个提示。感谢。

3 个答案:

答案 0 :(得分:5)

解决double的具体示例,它必须是特定于平台的优化,并且很可能g ++决定不做这样的事情。原因当然是任何使用double表示的平台,0.0并不意味着所有零字节。另外,设置为除零以外的任何数字都是完全不同的游戏,因为它不仅仅是将每个字节设置为零:需要遵循特定的模式。负数会变得更糟。

除非您有特定的分析信息,fill所花费的时间远远超过memset,否则我不会太担心。如果花费更长的时间,您可以手动调整以手动使用memset或尝试解决根本原因,需要重复设置为零。

答案 1 :(得分:4)

该标准不强制实现者使用memset()。但是gcc确实恰好在 memset() 的容器上使用std::fill() char

答案 2 :(得分:0)

它可以,而且通常不会,这是一种耻辱。至少它意味着代码大小的改进。问题在于,尽管人类很容易发现一个memset,但是有一大堆临时物体和其他由此产生的残余物,并且它的优化并不容易。

遗憾的是,生成简单循环是因为它至少简化为:

const T val(0.0);
for (size_t i = 0; i < 30000; ++i) vec.data[i] = double(val);

...但它没有做出最后的演绎飞跃,通过一个pod类型数组初始化为相同值的0..30000循环最好用memset完成。正如wilhelmtell所提到的,一些实现专注于几个pod类型,其中有很大的胜利(在chars上循环很慢)。我真的希望编译器能够实现最后的飞跃,因为如果人们知道这种情况不会发生,它将有助于使用容器库。