bytes offset 6800 ~ 6900: 170884 times
bytes offset 6900 ~ 7000: 220944 times
bytes offset 7000 ~ 7100: 24216 times
bytes offset 7100 ~ 7200: 9576 times
bytes offset 7200 ~ 7300: 14813 times
bytes offset 7300 ~ 7400: 22109 times
bytes offset 7400 ~ 7500: 19748 times
bytes offset 7500 ~ 7600: 43110 times
bytes offset 7600 ~ 7700: 157976 times
...
bytes offset 121200 ~ 121300: 1514 times
bytes offset 121300 ~ 121400: 802 times
bytes offset 121400 ~ 121500: 606 times
bytes offset 121500 ~ 121600: 444 times
bytes offset 121600 ~ 121700: 398 times
max_bytes_offset 121703
min_bytes_offset 6848
--
Milo Yip
Twitter @miloyip
http://www.cnblogs.com/miloyip/
http://miloyip.seezone.net/
。先研究一下你们的方法~ 刚刚还有人建议我丢弃1300个桶+大小为10的双向链表的结构,用一个更大的hash table和双向链表来实现,好像效率会高很多,不过设计hash function又是一个问题。回复的好快。先研究一下你们的方法~ 刚刚还有人建议我丢弃1300个桶+大小为10的双向链表的结构,用一个更大的hash table和双向链表来实现,好像效率会高很多,不过设计hash function又是一个问题。
不算cache的话,这部分的程序总共占内存才50k左右~ 130k在PC上看起来不多,在移动平台上就不一样啦,有的手机总共内存才2M左右,130k就很大了
直接用数组就可以了, 不懂为什么需要用双向链表和hash表.
2010/7/7 Lucas Zhang <zhangq...@gmail.com>:
2010/7/7 DaiZW <shinys...@gmail.com>:
你说的这种方法似乎应该叫做"时钟页面替换算法"? 是"第二次机会页面置换算法"的一种变形, 不是基于时间计数而是基于访问计数的.
这种方法的效率应该还不错.
总之淘汰策略有很多啦, 重要的是选择合适的算法和合适的数据结构.
2010/7/7 Lucas Zhang <zhangq...@gmail.com>:
--
在 2010年7月8日上午1:49,chuang <lichua...@gmail.com> 寫道:
> 不明白为什么需要O(N)遍历呢?如果一个链表上存放的是被访问的数据,假如访问过一次的数据每次往前走一步,那么最少被访问到的在链表尾了,不需要遍历即可得到.
>
> 2010/7/7 Milo Yip <mil...@gmail.com>
>>
>> 我之前建議用page,所有pages放進一個連續buffer裡。
>> 另外做一個雙向鏈表做LRU。不用O(n)遍歷可以取得least recently used page。
>> 怕寫錯可先用數組遍歷也可以,page數量不多。
>>
>> 在 2010年7月7日下午10:31,Lucas Zhang <zhangq...@gmail.com> 寫道:
>> > 用数组的话 LRU怎么对块的淘汰进行管理呢?不需要遍历么?
>> >
>> > 双向链表的优点是每次淘汰的都是尾指针指向的元素,每次加入的元素都在最前面,每次读取的元素次数加一后,可以很方便的移动到有序的位置。数组的话这些开销就很大了吧。
--
我觉得在数据结构上调优的效果受到紧张的空间和高效的制约,无论如何也没有完美的方案,cache的结构越简单越好,bucket/Array已经足够好了。根据数据的特性设计一个好的hash,这个上面获得的提升才会大。
在 2010年7月8日 上午10:04,Changsheng Jiang <jiang...@gmail.com>写道:
不懂手机平台, 想在PC上, 这种事情一般是交给内核做. 应用程序为降低系统调用次数, 一般是用 mmap 映射文件.
最大才 121703, 内存也存得下吧?
Hash表, 在 PC 上, 开放地址碰撞方案, 比链表方案要快, 减少指针跳跃, 也省指针内存. 只是要求哈稀函数不能太差.
Changsheng Jiang
2010/7/8 DaiZW <shinys...@gmail.com>或许lz不需要这么多个桶(页/块, whatever).
如果用链表/hash表这类数据结构, 光是指针的空间开销就不小.
所以还是建议使用长度较小的数组(例如<20), 即使O(N)遍历, 效率也不会差到哪里去.
关联式cache的复杂度既不是O(lgN)也不是O(N)而是O(1),原理跟hash表非常相似,定位是O(1),淘汰也是O(1),这么说够清楚了吧?
至于你举的这个例子:“这个道理很简单, INT i,j; i * j,可以是O1的复杂度,也可能是O(size(i)*size(j))的复杂度,就是看你硬件支持不支持,值域够不够大....”,我认为是不正确的,因为讨论BigO的时候,我们是以N趋向于无穷取极限来算BigO的,硬件虽然可以制造支持很多位的乘法器,但不可能制造出无穷多位的乘法器,所以如果以位数N来算BigO的话,那么不管什么硬件都是O(N*N)的,否则就会搞出什么O(7),O(32)这样的笑话出来了。
在 2010年7月8日 下午1:48,qiaojie <qia...@gmail.com>写道:
关联式cache的复杂度既不是O(lgN)也不是O(N)而是O(1),原理跟hash表非常相似,定位是O(1),淘汰也是O(1),这么说够清楚了吧?我理解你的结论,但是仍然未理解“关联式cache”,抱歉。
至于你举的这个例子:“这个道理很简单, INT i,j; i * j,可以是O1的复杂度,也可能是O(size(i)*size(j))的复杂度,就是看你硬件支持不支持,值域够不够大....”,我认为是不正确的,因为讨论BigO的时候,我们是以N趋向于无穷取极限来算BigO的,硬件虽然可以制造支持很多位的乘法器,但不可能制造出无穷多位的乘法器,所以如果以位数N来算BigO的话,那么不管什么硬件都是O(N*N)的,否则就会搞出什么O(7),O(32)这样的笑话出来了。你可能理解错了我这里的INT,不仅仅是C++语言里的int,而是抽象的int。我用了size而不是sizeof。或许用length/bits/bytes会更准确点?一个事实是,我们平时在算复杂度时,一个整数乘法是看作O(1)的。我们并未讲清楚这个整数是怎么表示的,例如,是否必须是定长的,值域是有限的,补码表示等等限定,甚至,在TAOCP那个机器里面还搞了个10进制的表示。无所谓,不影响复杂度分析,是吧?但是,实际上我们是有个隐含前提的,那就是i*j一定能在常数时间内完成。然而这一假设不总是正确的。考虑一下,无限精度(或者,现实一点,超大尺度)的整数乘法呢?你还能认为i*j操作就是常数?不是我杜撰,有大整数运算库吧?
在 2010年7月8日 下午1:48,qiaojie <qia...@gmail.com>写道:关联式cache的复杂度既不是O(lgN)也不是O(N)而是O(1),原理跟hash表非常相似,定位是O(1),淘汰也是O(1),这么说够清楚了吧?我理解你的结论,但是仍然未理解“关联式cache”,抱歉。至于你举的这个例子:“这个道理很简单, INT i,j; i * j,可以是O1的复杂度,也可能是O(size(i)*size(j))的复杂度,就是看你硬件支持不支持,值域够不够大....”,我认为是不正确的,因为讨论BigO的时候,我们是以N趋向于无穷取极限来算BigO的,硬件虽然可以制造支持很多位的乘法器,但不可能制造出无穷多位的乘法器,所以如果以位数N来算BigO的话,那么不管什么硬件都是O(N*N)的,否则就会搞出什么O(7),O(32)这样的笑话出来了。你可能理解错了我这里的INT,不仅仅是C++语言里的int,而是抽象的int。我用了size而不是sizeof。或许用length/bits/bytes会更准确点?一个事实是,我们平时在算复杂度时,一个整数乘法是看作O(1)的。我们并未讲清楚这个整数是怎么表示的,例如,是否必须是定长的,值域是有限的,补码表示等等限定,甚至,在TAOCP那个机器里面还搞了个10进制的表示。无所谓,不影响复杂度分析,是吧?但是,实际上我们是有个隐含前提的,那就是i*j一定能在常数时间内完成。然而这一假设不总是正确的。考虑一下,无限精度(或者,现实一点,超大尺度)的整数乘法呢?你还能认为i*j操作就是常数?不是我杜撰,有大整数运算库吧?不知道你是否还觉得这是个笑话。
http://en.wikipedia.org/wiki/Multiplication_algorithm從 O(n^2) 到 2007年的 n log(n) 2Θ(log*(n))
我覺得,應該是要決定問題中那些是變量,那些是常量,不然沒法談complexity。例如只考慮32-bit加數,32可作為常量。那麼32-bit n個值的和是O(n)。若要計算n個m-bit值的和,就是O(nm)。
2010/7/8 wing fire <wing...@gmail.com>
2010/7/8 wing fire <wing...@gmail.com>
2010/7/8 wing fire <wing...@gmail.com>
绝圣弃知,大盗乃止;擿玉毁珠,小盗不起;
2010/7/8 wing fire <wing...@gmail.com>
回复的好快<330.gif>。先研究一下你们的方法~ 刚刚还有人建议我丢弃1300个桶+大小为10的双向链表的结构,用一个更大的hash table和双向链表来实现,好像效率会高很多,不过设计hash function又是一个问题。
On Jul 7, 4:40 pm, Lucas Zhang <zhangqing1...@gmail.com> wrote:
> 我现在在做一个手机平台上的软件,现在的I/O瓶颈是一个用seek读取img文件的函数。在我的测试里,一共调用了这个函数7480325次,读取的bytes
> offset位置是从6800到130000,也就是说,平均一个位置的byte会被重复读到平均100次左右(实际情况是有的byte会被读到3到4次,有的会被读到1000次以上)。下面是一些统计数据:
>
> bytes offset 6800 ~ 6900: 170884 times
> bytes offset 6900 ~ 7000: 220944 times
> bytes offset 7000 ~ 7100: 24216 times
> bytes offset 7100 ~ 7200: 9576 times
> bytes offset 7200 ~ 7300: 14813 times
> bytes offset 7300 ~ 7400: 22109 times
> bytes offset 7400 ~ 7500: 19748 times
> bytes offset 7500 ~ 7600: 43110 times
> bytes offset 7600 ~ 7700: 157976 times
> ...
> bytes offset 121200 ~ 121300: 1514 times
> bytes offset 121300 ~ 121400: 802 times
> bytes offset 121400 ~ 121500: 606 times
> bytes offset 121500 ~ 121600: 444 times
> bytes offset 121600 ~ 121700: 398 times
>
> max_bytes_offset 121703
> min_bytes_offset 6848
>
> 于是我想到做一个cache来优化函数的性能。由于之前也没怎么接触过cache,仅限于课本上的一点知识,我在google了一番后,发现比较好的方法是用hash表和双向链表来实现LRU策略的cache.这里有个
> 链接 <http://stackoverflow.com/questions/3027484/lru-caches-in-c>。如果要把所有位置的数据都搬到内存的话,大概是130KB左右。我想到一个简单的方法,用1300个桶来hash