优化c函数以删除比较
我一直在分析我们的应用程序,并发现了一些明显的问题,内存分配器被调用了很多次,并且占用了大量的时间(几%)。去年,我使内存分配器快了很多倍,但我仍然认为我可以加快一些。作为优化的一部分,我想加速量化分配大小的代码部分 内存分配器保留可用内存块的列表。有一个832个列表的数组。0..128k范围内的每个分配大小都有一个列表。所有来自0..128k的分配请求都被转换为832个量子中的一个(量子是正确的词吗?)832是任意的,结果是我提出了下面的方案。我平衡了不浪费内存和大量重用的愿望。此外,我希望使用尽可能少的位来存储分配的大小。在我们的应用程序中,对小尺寸的要求远高于对大尺寸的要求,即对小尺寸的重用更高。所有内容都与8字节对齐,因此最小的量子是8。我选择将256字节以下的所有分配量化为8字节,以避免浪费超过对齐要求的ram。另外,为了节省空间,当内存被添加到空闲内存列表中时,我使用分配内存的前8个字节作为下一个指针,因此我也不能低于8个字节。从2..8k开始,请求量为32字节。从8..32k到128字节。从32..128k到512字节。随着请求大小的增加,您可以使用更大的量子,并且仍然可以减少浪费的内存的%。因为我只有832个大小,所以重用率很高,即使对于更大/更稀有的分配也是如此 下面是量化分配请求的函数。iRecycle是列表数组的索引。从0到831优化c函数以删除比较,c,performance,optimization,C,Performance,Optimization,我一直在分析我们的应用程序,并发现了一些明显的问题,内存分配器被调用了很多次,并且占用了大量的时间(几%)。去年,我使内存分配器快了很多倍,但我仍然认为我可以加快一些。作为优化的一部分,我想加速量化分配大小的代码部分 内存分配器保留可用内存块的列表。有一个832个列表的数组。0..128k范围内的每个分配大小都有一个列表。所有来自0..128k的分配请求都被转换为832个量子中的一个(量子是正确的词吗?)832是任意的,结果是我提出了下面的方案。我平衡了不浪费内存和大量重用的愿望。此外,我希望使
void GetAlignedSize(QWORD cb, QWORD& cbPack8, WORD& iRecycle) {
// we assume cb is small, so the first 'if' will be hit the most.
if (cb < 0x000800 - 0x0007) { // 0k..2k = 8 byte chunks
cb += 0x0007; cbPack8 = cb & (~0x0007); // pad to 8
iRecycle = 000 + WORD(cb >> 3);
} else if (cb < 0x002000 - 0x001f) { // 2k..8k = 32 byte chunks
cb += 0x001f; cbPack8 = cb & (~0x001f); // pad to 32
iRecycle = 192 + WORD(cb >> 5);
} else if (cb < 0x008000 - 0x007f) { // 8k..32k = 128 byte chunks
cb += 0x007f; cbPack8 = cb & (~0x007f); // pad to 128
iRecycle = 384 + WORD(cb >> 7);
} else if (cb < 0x020000 - 0x01ff) { // 32k..128k = 512 byte chunks
cb += 0x01ff; cbPack8 = cb & (~0x01ff); // pad to 512
iRecycle = 576 + WORD(cb >> 9);
} else {
cbPack8 = Pack8(cb);
iRecycle = 0;
}
}
void GetAlignedSize(QWORD cb、QWORD和cbPack8、WORD和iRecycle){
//我们假设cb很小,所以第一个“如果”的命中率最高。
如果(cb<0x000800-0x0007){//0k..2k=8字节块
cb+=0x0007;cbPack8=cb&(~0x0007);//填充到8
iRecycle=000+字(cb>>3);
}else如果(cb<0x002000-0x001f){//2k..8k=32字节块
cb+=0x001f;cbPack8=cb&(~0x001f);//填充到32
iRecycle=192+字(cb>>5);
}else如果(cb<0x008000-0x007f){//8k..32k=128字节块
cb+=0x007f;cbPack8=cb&(~0x007f);//填充到128
iRecycle=384+字(cb>>7);
}else如果(cb<0x020000-0x01ff){//32k..128k=512字节块
cb+=0x01ff;cbPack8=cb&(~0x01ff);//填充到512
iRecycle=576+字(cb>>9);
}否则{
cbPack8=Pack8(cb);
i循环=0;
}
}
问题来了!我怎样才能做类似的事情,只有位操纵。我想去掉compare语句,因为我认为它会破坏cpu流水线。只要量化随大小而增加,并且128k以下大小的#很小,任何方案都是可行的。我希望这将消除最后一种情况,并且iRecycle将无限制地增加,因此我们可以将iRecycle更改为不同大小的整数
谢谢你的帮助 最明显的做法是使用表格。我怀疑这样的计划会更快,但好奇的是 …因此,为了创建基线,我调整了您的函数(用C呈现): 设置循环是:
srand(314159) ;
for (int i = 0 ; i < trial_count ; ++i)
{
int r ;
size_t mx, mn ;
r = rand() % 1000 ;
if (r < 800)
{
mn = 1 ;
mx = 0x00800 ;
}
else if (r < 950)
{
mn = 0x00801 ;
mx = 0x02000 ;
}
else if (r < 990)
{
mn = 0x02001 ;
mx = 0x08000 ;
}
else if (r < 999)
{
mn = 0x08001 ;
mx = 0x20000 ;
}
else
{
mn = 0x20001 ;
mx = 0x80000 ;
} ;
test_values[i] = (rand() % (mx - mn + 1)) + mn ;
} ;
总的来说(阅读并叹气)快了8%:-(
<>我很无聊。< /P>第一次的情况下,作为所有调用的百分比,多少次出现?这看起来是C++,而不是C,只是引用引用。你使用什么编译器和优化标志?最近的4.9次尝试(使用<代码> GCC-4.9- Munt=本机FLTO -O3 < /代码>编译和链接)?249的cb命中第一个if。250-256的cb命中第二个if,但仍量化为256。将第一个if重写为if(cb<0x800)对所有其他IFS也一样。边际改进,但更容易阅读。OOP抱歉。MSVC编译器有完全的优化。它是C++,但是C是好的。@ AIR:我最初把这些行每一行都排成一行,这样所有的东西都排好了,你可以看到应用的位模式。谢谢你的想法。哇,我没有想到T。可以。我可以将表定位在与代码相同的段中,因此我不需要额外的TLB命中。如果表非常小,它可能会在整个执行过程中保留在二级缓存中,因为它的命中率很高。这可能是表查找的一个非常好的候选。我们不必完全匹配原始函数。我认为我们可以表中包含32个条目,并使用msb作为索引。msb只有一条指令。这将消除<0x20000 cmp。稍后代码中会进行比较,以查找索引为零的索引。我可以将其更改为index>max recycle list。嗯,
static uint
get_aligned_size_1(size_t size, size_t* rsize)
{
static const uint tb[0x40] =
{
/* 0x00 */ (0x007 << 16) + ((256 - 64) * 0) + 3,
/* 0x01 */ (0x01F << 16) + ((256 - 64) * 1) + 5,
/* 0x02 */ (0x01F << 16) + ((256 - 64) * 1) + 5,
/* 0x03 */ (0x01F << 16) + ((256 - 64) * 1) + 5,
/* 0x04 */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x05 */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x06 */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x07 */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x08 */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x09 */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x0A */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x0B */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x0C */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x0D */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x0E */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x0F */ (0x07F << 16) + ((256 - 64) * 2) + 7,
/* 0x10 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x11 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x12 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x13 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x14 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x15 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x16 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x17 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x18 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x19 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x1A */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x1B */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x1C */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x1D */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x1E */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x1F */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x20 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x21 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x22 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x23 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x24 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x25 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x26 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x27 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x28 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x29 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x2A */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x2B */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x2C */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x2D */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x2E */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x2F */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x30 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x31 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x32 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x33 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x34 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x35 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x36 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x37 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x38 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x39 */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x3A */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x3B */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x3C */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x3D */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x3E */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
/* 0x3F */ (0x1FF << 16) + ((256 - 64) * 3) + 9,
} ;
size_t sx = size - 1 ;
if (size <= 0x20000)
{
uint tx ;
tx = tb[sx >> 11] ;
*rsize = (sx | (tx >> 16)) + 1 ;
return (sx >> (tx & 0xF)) + (tx & 0xFFF0) ;
} ;
*rsize = 0 ;
return 64 + ((256 - 64) * 4) ;
} ;
Setup: 15.610 secs: user 15.580 system 0.000 -- 500 million
Branches: 1.910 secs: user 1.910 system 0.000
Table 1: 1.840 secs: user 1.830 system 0.000
srand(314159) ;
for (int i = 0 ; i < trial_count ; ++i)
{
int r ;
size_t mx, mn ;
r = rand() % 1000 ;
if (r < 800)
{
mn = 1 ;
mx = 0x00800 ;
}
else if (r < 950)
{
mn = 0x00801 ;
mx = 0x02000 ;
}
else if (r < 990)
{
mn = 0x02001 ;
mx = 0x08000 ;
}
else if (r < 999)
{
mn = 0x08001 ;
mx = 0x20000 ;
}
else
{
mn = 0x20001 ;
mx = 0x80000 ;
} ;
test_values[i] = (rand() % (mx - mn + 1)) + mn ;
} ;
static uint
get_aligned_size_5(size_t size, size_t* rsize)
{
static const uint8_t ts[0x40] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F
/* 0x00 */ 3,
/* 0x01..0x03 */ 5, 5, 5,
/* 0x04..0x0F */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
/* 0x10..0x1F */ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
/* 0x20..0x2F */ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
/* 0x30..0x3F */ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
} ;
static const uint tb[16] =
{
/* 0 */ 0,
/* 1 */ 0,
/* 2 */ 0,
/* 3 */ ((256 - 64) / 2) * (3 - 3),
/* 4 */ 0,
/* 5 */ ((256 - 64) / 2) * (5 - 3),
/* 6 */ 0,
/* 7 */ ((256 - 64) / 2) * (7 - 3),
/* 8 */ 0,
/* 9 */ ((256 - 64) / 2) * (9 - 3),
/* 10 */ 0,
/* 11 */ 0,
/* 12 */ 0,
/* 13 */ 0,
/* 14 */ 0,
/* 15 */ 0,
} ;
size_t sx = size - 1 ;
if (size <= 0x20000)
{
uint8_t s ;
s = ts[sx >> 11] ;
*rsize = (sx | (((size_t)1 << s) - 1)) + 1 ;
return (sx >> s) + tb[s] ;
} ;
*rsize = 0 ;
return 64 + ((256 - 64) * 4) ;
} ;
Setup: 15.610 secs: user 15.580 system 0.000 -- 500 million
Branches: 1.910 secs: user 1.910 system 0.000
Table 1: 1.840 secs: user 1.830 system 0.000
Table 5: 1.750 secs: user 1.750 system 0.000