📜  LRU 近似(二次机会算法)

📅  最后修改于: 2022-05-13 01:56:11.574000             🧑  作者: Mango

LRU 近似(二次机会算法)

如果您不熟悉最近最少使用的算法,请查看最近最少使用的算法(页面替换)

该算法结合了使用类似于 FIFO(FIFO(页面替换))的队列以及使用数组来跟踪用于为排队页面提供“第二次机会”的位的组合。算法是如何工作的:

解释:
在这种情况下,对于 bitref 中的索引,这些位像往常一样设置为 1,直到队列已满。
一旦队列已满,根据 FIFO 页替换算法,我们应该摆脱队列的前端(如果元素是错误/未命中)。但在这里我们不这样做。

相反,我们首先检查它的引用位(又名 bitref)是否为 0 或 1(假或真)。如果为 0(假),我们将其从队列中弹出并将等待元素推入队列。但是如果它是 1(真),我们就将它的引用位 (bitref) 设置为 0 并将它移到队列的后面。我们继续这样做,直到我们遇到队列的前端,使其前端值的引用位 (bitref) 为 0 (false)。

然后我们按照通常的方式将它从队列中移除并将等待元素推入队列。



如果等待元素已经在队列中怎么办?我们只是将其参考位 (bitref) 设置为 1 (true)。


我们现在将所有像 2, 4, 1 这样的值向后移动,直到遇到 3,其 bitref 为 0。将 2, 4, 1 向后移动时,我们将它们的 bitref 值设置为 0。

所以现在,问题是当它清楚地实现 FIFO 而不是 LRU 时,这是 LRU 的近似值。嗯,这是通过为队列的前面提供第二次机会(在 FIFO 的情况下会被弹出和替换)来实现的。在这里,第二次机会基于这样一个事实:如果元素“最近”被看到,它的参考位 (bitref) 被设置为 1 (true)。如果最近没有看到它,我们就不会将其参考位 (bitref) 设置为 1 (true) 并因此将其删除。因此,这就是为什么它是近似值而不是 LRU 或 FIFO。

下面是上述方法的实现:

// C++ implementation of the approach
#include 
using namespace std;
  
// Function to find an element in the queue as
// std::find does not work for a queue
bool findQueue(queue q, int x)
{
    while (!q.empty()) {
        if (x == q.front())
            return true;
        q.pop();
    }
  
    // Element not found
    return false;
}
  
// Function to implement LRU Approximation
void LRU_Approximation(vector t, int capacity)
{
    int n = t.size();
    queue q;
  
    // Capacity is the size of the queue
    // hits is number of times page was
    // found in cache and faults is the number
    // of times the page was not found in the cache
    int hits = 0, faults = 0;
  
    // Array to keep track of bits set when a
    // certain value is already in the queue
    // Set bit --> 1, if its a hit
    // find the index and set bitref[index] = 1
    // Set bit --> 0, if its a fault, and the front
    // of the queue has bitref[front] = 1, send front
    // to back and set bitref[front] = 0
    bool bitref[capacity] = { false };
  
    // To find the first element that does not
    // have the bitref set to true
    int ptr = 0;
  
    // To check if the queue is filled up or not
    int count = 0;
    for (int i = 0; i < t.size(); i++) {
        if (!findQueue(q, t[i])) {
  
            // Queue is not filled up to capacity
            if (count < capacity) {
                q.push(t[i]);
                count++;
            }
  
            // Queue is filled up to capacity
            else {
                ptr = 0;
  
                // Find the first value that has its
                // bit set to 0
                while (!q.empty()) {
  
                    // If the value has bit set to 1
                    // Set it to 0
                    if (bitref[ptr % capacity])
                        bitref[ptr % capacity] = !bitref[ptr % capacity];
  
                    // Found the bit value 0
                    else
                        break;
                    ptr++;
                }
  
                // If the queue was empty
                if (q.empty()) {
                    q.pop();
                    q.push(t[i]);
                }
  
                // If queue was not empty
                else {
                    int j = 0;
  
                    // Rotate the queue and set the front's
                    // bit value to 0 until the value where
                    // the bitref = 0
                    while (j < (ptr % capacity)) {
                        int t1 = q.front();
                        q.pop();
                        q.push(t1);
                        bool temp = bitref[0];
  
                        // Rotate the bitref array
                        for (int counter = 0; counter < capacity - 1; counter++)
                            bitref[counter] = bitref[counter + 1];
                        bitref[capacity - 1] = temp;
                        j++;
                    }
  
                    // Remove front element
                    // (the element with the bitref = 0)
                    q.pop();
  
                    // Push the element from the
                    // page array (next input)
                    q.push(t[i]);
                }
            }
            faults++;
        }
  
        // If the input for the iteration was a hit
        else {
            queue temp = q;
            int counter = 0;
            while (!q.empty()) {
                if (q.front() == t[i])
                    bitref[counter] = true;
                counter++;
                q.pop();
            }
            q = temp;
            hits++;
        }
    }
    cout << "Hits: " << hits << "\nFaults: " << faults << '\n';
}
  
// Driver code
int main()
{
    vector t = { 2, 3, 2, 1, 5, 2, 4, 5, 3, 2, 5, 2 };
    int capacity = 4;
    LRU_Approximation(t, capacity);
  
    return 0;
}
输出:
Hits: 6
Faults: 6

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。