Closed d-engler closed 1 week ago
What you've laid out in the PDF seems good, makes sense to me, anyways.
I think regarding the Python implementation, in my opinion, we are going to want at least one structure with access via named keys (dictionary or instances of a class we create), for the individual entries / cache lines.
Within each set, I'm not sure I see a benefit to a dictionary over a list, since we need to check each item for our matching tag bits either way. ~I don't think we could have a dictionary keyed by the tag bits only without risking collisions.~ I think we could use a dictionary and key by tag, which could make sense for quickly retrieving or removing an entry. Since it's only 16 items in each set, going for a binary search tree or something seems like it might be overkill (though hard to say given the scale we'll be operating on in terms of number of transactions). I think this might depend on how our PLRU is implemented. Maybe something like a priority queue with the PLRU bits to have quick access to eviction, and linear search for the matching tag?
For the sets, I was initially thinking a dictionary, since Mark led us down the path of hashmaps. But @mdhardenburgh got a good clarification there, that he didn't necessarily intend to send us in that direction, I think it was mainly a part of his analogy. I think we could have a list at that level as well, since each index could just be used directly as the index for the list item. If we did a dictionary at that level instead, it could just be keyed by the index - I'm not sure I see any major pros or cons to either option. Might need to dig deeper into the underlying Python implementation if we want to differentiate on things like overall memory usage or speed.
So I guess to provide a visual, this is a very simplified version of what I was thinking:
# Each cache line could be a dictionary or instance of a class we create, with fields we can access by name
cache_line_0 = { "tag": 0b<add the tag bits here>, "data": None, "MESI": 0b00, "valid": 0, "dirty": 0 }
# main cache data structure is a list, where each index points to a list of all the ways in the set
cache = []
# example index 256 is another list representing the ways in the set
# I think this could instead be a dictionary keyed by tag as an alternative
cache[0b100000000] = [cache_line_0, cache_line_1,...,cache_line_15];
# retrieve a cache line:
for way in cache[0b100000000]:
if way["tag"] == target_tag:
cache_hit(way) # do something with the cache line
else:
cache_miss() # handle the miss
I'm curious to know what @mdhardenburgh and @reecewayt had in mind though, and if you've generated any more ideas after looking at Python data structures more @d-engler.
Hmm. Yeah, I guess it could even be a list of lists. The outer structure (sets) has a simple sequential index so list seems to work there, but for the inner structure (ways) I guess the question is what do we want to index on? If it is the way, then a list works, but if it is the tag, I think we need a dictionary.
The ability to use a string as a key for each field in the tag array seems like it would make life easier, too.
@reecewayt and I were chatting about the PLRU algorithm, and since it returns an index for the victim to be evicted, it seems like it could make sense to start with the set data structure as a list of dictionaries. The victim index would be the way to target, and the dictionaries in each way would be for the entries so we could access each field by name.
The idea here would be to start as simple as possible, leaving room to change if we find the need, e.g. we could promote the dictionaries for cache entries to class instances if we find a need to add specific operations, or we could look into whether there's an ordered dictionary option that would work for indexing in to target a victim and allow for tags as keys.
@d-engler how does that sound?
@nkanderson My thought exactly.
@nkanderson @reecewayt Are we ready to add the MESI bits to the sketch? I left them out pending that lecture, but if it's as simple as another two bits in the tag array, then I can revise.
Are we ready to add the MESI bits to the sketch? I left them out pending that lecture, but if it's as simple as another two bits in the tag array, then I can revise.
Yeah, I think adding those 2 bits for MESI sounds good. I believe @reecewayt had one modification for the PLRU since I think it's on the set level instead of line level? I still need to review that content a bit myself, but that's what it sounded like when he and I talked about it earlier today.
@d-engler Yes go ahead and add the MESI as well to the sketch. My one comment is that each set will have 15 plru bits, while your sketch shows 15 plru bits per cache line.
My one comment is that each set will have 15 plru bits, while your sketch shows 15 plru bits per cache line.
Oops, that's right.
Ok, Just pushed a revised sketch.
@nkanderson @reecewayt Added a directory under src in this branch that contains a draft class to instantiate a cache data structure (cachestruct.py) and a brief script to demonstrate it (dstest.py). Take a look and offer your critiques, commendations, or condemnations. I'm not much of a pythonista so maybe there is a more elegant way to do it. Presumably we can add a method or methods to make updating values in the structure less cumbersome/more fine tuned to our operations.
Also, that linter is fucking picky. My big complaint about python is the way it cares about white space so that thing was needling me...
@reecewayt I agree this approach is more memory efficient (although I'm not sure it matters on typical hardware). And if were not married to string indexes then lists are fine. Additionally, the methods look good, so I think this is looking slick. Learning a lot about python with the project.
@d-engler Can you remove the python files from this PR, and then we can merge it to main?
@d-engler Can you remove the python files from this PR, and then we can merge it to main?
Done.
Here is a draft sketch of the data structure. This is just the sketch, not the code. I think this might change once we know more about implementing MESI. That may mean another bit field. As for implementing it, it seems the python way would be nested dictionaries, but I'm gonna do a little python data structures review first.