如何使用`int32_t`值快速填充内存?

Kir*_*sky 11 c++ memory windows winapi visual-c++

是否有一个函数(SSEx内在函数可以),它将用指定的int32_t值填充内存?例如,当此值等于0xAABBCC00结果时,内存应如下所示:

AABBCC00AABBCC00AABBCC00AABBCC00AABBCC00
AABBCC00AABBCC00AABBCC00AABBCC00AABBCC00
AABBCC00AABBCC00AABBCC00AABBCC00AABBCC00
AABBCC00AABBCC00AABBCC00AABBCC00AABBCC00
...
Run Code Online (Sandbox Code Playgroud)

我可以使用std::fill或简单的for循环,但它不够快.


在程序开始时仅调整一次矢量的大小,这不是问题.瓶颈正在填补记忆.

简化代码:

struct X
{
  typedef std::vector<int32_t> int_vec_t;
  int_vec_t buffer;

  X() : buffer( 5000000 ) { /* some more action */ }
  ~X() { /* some code here */ }

  // the following function is called 25 times per second
  const int_vec_t& process( int32_t background, const SOME_DATA& data );
};

const X::int_vec_t& X::process( int32_t background, const SOME_DATA& data )
{
    // the following one string takes 30% of total time of #process function
    std::fill( buffer.begin(), buffer.end(), background );

    // some processing
    // ...

    return buffer;
}
Run Code Online (Sandbox Code Playgroud)

wj3*_*j32 9

我就是这样做的(请原谅我的微软):

VOID FillInt32(__out PLONG M, __in LONG Fill, __in ULONG Count)
{
    __m128i f;

    // Fix mis-alignment.
    if ((ULONG_PTR)M & 0xf)
    {
        switch ((ULONG_PTR)M & 0xf)
        {
            case 0x4: if (Count >= 1) { *M++ = Fill; Count--; }
            case 0x8: if (Count >= 1) { *M++ = Fill; Count--; }
            case 0xc: if (Count >= 1) { *M++ = Fill; Count--; }
        }
    }

    f.m128i_i32[0] = Fill;
    f.m128i_i32[1] = Fill;
    f.m128i_i32[2] = Fill;
    f.m128i_i32[3] = Fill;

    while (Count >= 4)
    {
        _mm_store_si128((__m128i *)M, f);
        M += 4;
        Count -= 4;
    }

    // Fill remaining LONGs.
    switch (Count & 0x3)
    {
        case 0x3: *M++ = Fill;
        case 0x2: *M++ = Fill;
        case 0x1: *M++ = Fill;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对不起,我是一个普通的C家伙.我对std,fill或std :: fill一无所知. (6认同)
  • 我会对如何与std :: fill进行性能比较感兴趣. (2认同)

Mar*_*k B 6

我不得不问:你有没有明确地描述std::fill并证明它是性能瓶颈?我猜它是以一种非常有效的方式实现的,这样编译器就可以自动生成适当的指令(例如-march在gcc上).

如果它是瓶颈,它仍然可以从算法重新设计(如果可能的话)中获得更好的好处,以避免设置如此多的内存(显然是一遍又一遍),这样你再使用哪种填充机制并不重要.


Kir*_*sky 6

感谢大家的回答。我已经检查了wj32 的解决方案,但它显示的时间与std::fill执行的非常相似。我当前的解决方案(在 Visual Studio 2008 中)的运行速度比std::fill借助该函数快 4 倍memcpy

 // fill the first quarter by the usual way
 std::fill(buffer.begin(), buffer.begin() + buffer.size()/4, background);
 // copy the first quarter to the second (very fast)
 memcpy(&buffer[buffer.size()/4], &buffer[0], buffer.size()/4*sizeof(background));
 // copy the first half to the second (very fast)
 memcpy(&buffer[buffer.size()/2], &buffer[0], buffer.size()/2*sizeof(background));
Run Code Online (Sandbox Code Playgroud)

在生产代码中,需要添加检查是否buffer.size()能被 4 整除,并为此添加适当的处理。