我的时钟缓存无效。我在做什么:
如果key为self.items_to_index:将bit设置为1,则返回self.buffers中的值。
如果不是:
在输入上调用函数以获取newval。
调用self._increment()直到我们在self.buffers中看到一个位设置为0的条目。
self.buffers [self._p]现在等于[newval,1]
删除_p等于该条目的字典条目。
然后执行self.items_to_index [k] = _p。
增加p。
我上面描述的代码是:[not working]
def __getitem__(self, k):
"""
Returns func(k) using the buffer to cache limited results.
:param k: Value to be evaluated
>>> clock = ClockMap(4, lambda x: x ** 2)
>>> clock[4]
16
>>> clock[3]
9
>>> clock._p
2
"""
#when clock[index] is queried, this _getitem__ function is called
if k in self.items_to_index:
#hit
index = self.items_to_index[k]
entry = self.buffers[index]
entry[1] = 1
return entry[0]
else:
val = self.fn(k)
while self.buffers[self._p][1] == 1:
self.buffers[self._p][1] = 0
self._increment()
self.buffers[self._p] = [val, 1]
for inputx, bufflocation in self.items_to_index.iteritems():
if bufflocation == self._p:
self.items_to_index.pop(inputx)
self.items_to_index[k] = bufflocation
break
self._increment()
return val
整个班级都附上她以供参考:
class ClockMap:
def __init__(self, cacheSize, func):
"""
Do not change existing variables.
[Optional] You are free to add additional items and methods.
"""
self.cacheSize = cacheSize #number of buffers
self.fn = func #function whose results that you will be caching
self._p = 0 # pointer
self._increments = 0
self._miss_count = 0
self.buffers = [[None, 0] for x in range(cacheSize)] #actual output vals of the func passed in
#hit: retrieve the value from the cache. Miss: reevaluate func with input, write to cache
self.items_to_index = {} # dict, input to buffer location, self.items_to_index[x] = buffer_index
def _increment(self):
"""
Do not change this method.
Updates the clock pointer. The modulo maintains the clock nature.
"""
self._increments += 1
self._p = (self._p + 1) % self.cacheSize
我如何测试这个和我的测试结果:
def test3ClockMap(ClockMap):
check_dir()
clock = ClockMap(4, lambda x: x ** 2)
requests = [1, 2, 3, 4, 1, 6, 1, 4, 7, 4, 7, 5, 4, 6]
with open(your_output + "task3ClockMap.txt", "wb") as f:
writer = csv.writer(f)
writer.writerow(["Request", "Result", "Pointer", "Increments"])
for r in requests:
writer.writerow([r, clock[r], clock._p, clock._increments])
diff_against_reference("task3ClockMap.txt", 3)
差异文件:
6,15c6,15
< 1,1,1,9
< 6,36,2,10
< 1,1,3,11
< 4,16,0,12
< 7,49,1,17
< 4,16,2,18
< 7,49,3,19
< 5,25,0,20
< 4,16,1,25
< 6,36,2,26
---
> 1,1,0,4
> 6,36,1,9
> 1,1,2,10
> 4,16,2,10
> 7,49,3,11
> 4,16,3,11
> 7,49,3,11
> 5,25,0,16
> 4,16,1,17
> 6,36,2,18
答案 0 :(得分:1)
我相信它是因为行
for inputx, bufflocation in self.items_to_index.iteritems():
self.items_to_index被初始化为空,并且不会在上面的循环之外更新,因此循环中的任何代码都不会运行。
答案 1 :(得分:1)
值永远不会添加到self.items_to_index
字典中,因此永远不会从缓存中返回值。您可以通过更改ClockMap.__getitem__()
来处理当前指针不在索引中的情况来解决这个问题:
for inputx, bufflocation in self.items_to_index.iteritems():
if bufflocation == self._p:
self.items_to_index.pop(inputx)
self.items_to_index[k] = bufflocation
break
else:
self.items_to_index[k] = self._p
请注意添加到else
循环的for
块。这样可以处理当前指针尚未存在于索引中并添加它的情况。
您的缓存类似于LRU缓存。如果您使用的是Python 3,则可能需要查看functools.lru_cache
装饰器,例如
from functools import lru_cache
@lru_cache()
def f(x):
return x**3
>>> f.cache_info()
CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)
>>> f(2)
8
>>> f.cache_info()
CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
>>> f(2)
8
>>> f.cache_info()
CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)