Как использовать несколько слоев кэша в C ++ (RAM, HDD, Cold) - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть простой класс данных POD, такой как

struct hash{
    char buffer[16];
};

Мне нужен вектор из множества экземпляров, который он точно не поместится в ОЗУ (20 ПБ). Концептуально он сгруппирован в вектор (дерево). Я хочу иметь способ иметь указатель, похожий на то, что скрывало бы ОЗУ, файловую систему, холодное хранилище и имел бы простой интерфейс типа массива \ указателя (делая fs, операции невидимыми после инициализации, но позволяя дать ему несколько мест для помещения данных в - ОЗУ, быстрый SSD, SSD, HDD, магнитная лента, облачные накопители)

Как это сделать в C ++?

Ответы [ 2 ]

1 голос
/ 02 мая 2019

На уровне языка это не поддерживается.

Одним из решений было бы использование отображенного в памяти файла, например, см .:

Создание сопоставления файлов с использованием больших страниц

Если вам нужно более независимое от платформы решение, возможно, вы могли бы использовать , который имеет некоторую поддержку файлов, отображаемых в память, а также в библиотеке .

Кроме того, вы всегда можете сделать указатель , как фасад объекта, для управления базовой логикой (аля. Умные указатели).

template<class T>
struct MyMappedPointerType {
  T& operator* MyPointerType();//derefence - may throw..
  //implement rest of semantics
};
0 голосов
/ 05 мая 2019

Я думаю, что обычно было бы использовать какую-то ручку.Затем, когда вы захотите получить доступ к объекту, вы передадите дескриптор функции, которая загрузит память и даст вам адрес, а затем закроете дескриптор.В C ++ вы должны использовать RAII.

#include <string>
#include <cstdio>

template <class T>
class Access
{
private:
    FILE* f= nullptr;
public:
    Access(const std::string& filename)
    {
        f= fopen(filename.data(), "rw");
    }

    ~Access()
    {
        fclose(f);
    }

    class WriteAccess
    {
        T buffer{};
        bool dirty= false;
        FILE* f;
        int64_t elementNumber;
    public:
        WriteAccess(FILE* f, int64_t elementNumber)
        : f(f)
        , elementNumber(elementNumber)
        {
            if (f) {
                fseek(f, elementNumber*sizeof(buffer), SEEK_SET);
                fread(&buffer, sizeof(buffer), 1, f);
            }
        }

        T& get() { dirty= true; return buffer; }
        const T& get() const { return buffer; }

        ~WriteAccess()
        {
            if (dirty && f) {
                fseek(f, elementNumber*sizeof(buffer), SEEK_SET);
                fwrite(&buffer, sizeof(buffer), 1, f);
            }
        }
    };

    WriteAccess operator[] (int64_t elementNumber)
    {
        return WriteAccess(f, elementNumber);
    }
};

struct SomeData
{
    int a= 0;
    int b= 0;
    int c= 0;
};

int main()
{
    Access<SomeData> myfile("thedata.bin");

    myfile[0].get().a= 1;
    auto pos1= myfile[1];

    pos1.get().a= 10;
    pos1.get().b= 10;
}

Конечно, вы предоставляете доступ для чтения и доступ для записи, вероятно, не используя fopen, а новые файлы c ++, , вы должны проверять ошибки , иможет быть, вы могли бы избавиться от функции get() в виде оператора преобразования в T.

Также следует заметить, что вы можете использовать подсчет ссылок, в моем простом примере класс Access должен выжить WriteAccess class.

Кроме того, вы должны заблокировать, если это будет использоваться более чем одним потоком, и я предположил, что вы не получите доступ к одному и тому же элементу дважды.

Или вы могли бытакже используйте доступ к файлам, отображенным в памяти, как они сказали вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...