我期待连续容器上的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或其他高级矢量化代码来完成。请给我一个提示。感谢。
答案 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上循环很慢)。我真的希望编译器能够实现最后的飞跃,因为如果人们知道这种情况不会发生,它将有助于使用容器库。