顯而易見的事情是使用一個表。我很懷疑,這樣的方案會更快,但好奇......
...所以,建立一個基線我調整你的函數(在C渲染它):
static uint
GetAlignedSize(size_t size, size_t* rsize)
{
size_t sx = size - 1 ;
if (size <= 0x00800)
{
*rsize = (sx | 0x007) + 1 ;
return (sx >> 3) + ((256 - 64) * 0) ;
} ;
if (size <= 0x02000)
{
*rsize = (sx | 0x01F) + 1 ;
return (sx >> 5) + ((256 - 64) * 1) ;
} ;
if (size <= 0x08000)
{
*rsize = (sx | 0x07F) + 1 ;
return (sx >> 7) + ((256 - 64) * 2) ;
} ;
if (size <= 0x20000)
{
*rsize = (sx | 0x1FF) + 1 ;
return (sx >> 9) + ((256 - 64) * 3) ;
} ;
*rsize = 0 ;
return 64 + ((256 - 64) * 4) ;
} ;
注意到本確定尺寸高達,包括 0x800與8字節單位等,並返回所有已知尺寸的「索引」0..831,和外部尺寸(不是1..832和0)的832。順帶一提,我想知道是否真的有用知道圓形大小?要解鎖塊,你需要「索引」,如果你需要可以擡頭的圓形尺寸? [披露:這還假定傳入請求大小不爲零......這使得在時序一個微小的改進!]
無論如何,最普遍的做法是,以錶帶動整個事情:
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) ;
} ;
其中掩模輪尺寸時,在「索引」基礎和以創建「索引」所要求的換擋都在表...手動填充到UINT。
我通過隨機選擇的請求大小定義了兩個函數:80%1..0x800,15%0x801..0x2000,4%0x2001..0x8000,0.9%0x8001..0x20000和0。1%外尺寸:
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 ;
} ;
觀察非常仔細地考慮設置5個億測試值的時間。表格版本的運行速度稍微快一點...(gcc 4.8,-O3)...但這是一個簡單功能的4%改進!請注意,表驅動版本更加靈活,並且可以在不更改代碼或運行時間的情況下添加更多的量子。
FWIW,掩模可以(明顯)被從移位構造,所以:
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
在一個整體(閱讀和嘆息)8%的速度:-(。
很好啊,我很無聊。
多久第一種情況下撞到,如所有電話的百分比?此外,這似乎是C++,而不是C,只是參考參數。 – user2357112
您使用哪種編譯器和優化標誌?您是否嘗試過使用最近的[GCC](http://gcc.gnu.org/)4.9(使用'gcc-4.9 -mtune = native -flto -O3'編譯和鏈接)? –
249擊中第一個if。 250-256的cb如果點擊第二個,但仍然量化爲256.如果if(cb <0x800)重寫第一個,並且對於所有其他if也是如此。邊際改進,但更容易閱讀。 –