Я имею дело с очень большими отображенными в память файлами (200+ ГБ), которые не могут быть полностью загружены в память, и доступ к ним осуществляется случайным образом. Сопоставленные файлы хранятся на массиве твердотельных накопителей, но я все еще нахожу, что доступ к необходимым частям по одной очень медленный, если только тот же поиск не был выполнен ранее, а используемые страницы уже были считаны в память.
Добавление нескольких потоков для чтения переменных в mmap одновременно значительно повышает скорость, и мне не удалось достичь верхней границы для улучшения в моем тестировании, но наличие более 1000 потоков приводит к тому, что openmp выдает ошибки, связанные с недоступностью ресурсов.
Я также попробовал madvise, чтобы сообщить ядру о конкретных частях, которые будут необходимы (MADV_WILLNEED), но ядро, кажется, не действует достаточно быстро, чтобы изменить ситуацию.
Я ищу способ одновременной предварительной выборки частей данных, необходимых непосредственно перед их фактическим использованием. Каков был бы наименее ресурсоемкий способ чтения переменной (или части размером с страницу памяти сопоставленного файла, содержащей ее), принудительно помещающей ее в память без блокировки чтения.
Если нельзя избежать блокирования, также будет работать способ запуска гораздо большего числа очень легких потоков, чтобы сделать чтение.
Вы, кажется, ответили на свой вопрос. Ваше единственное решение, кроме многопоточности, состоит в том, чтобы проходить через любое количество доступов, которые вы можете сделать madvise
для каждого. Затем через некоторое количество х madvise
s (скажем, 10000) вы вернетесь и получите доступ к памяти. Следует отметить, однако, что O / S делает НЕ гарантировать, что ввод / вывод будет выполнен в том порядке, в котором вызывается madvise. Следовательно, O / S может обработать первый madvise, а затем перейти к концу madvise или к тому, который имеет наименьший адрес, в основном, как ему угодно. Просто нет возможности значительно ускорить ввод / вывод до такой степени, как вы хотите.
Пример:
for(i=0; i < accesses + 10000; ++i)
{
madvise(access[i].addr, access[i].length, MADV_WILLNEED);
if(i >= 10000)
{
// Access location access[i-10000].addr
}
}
Однако вы должны спросить себя, действительно ли отображение файла является тем, что вы хотите сделать, если используете произвольный доступ. Казалось бы, асинхронный ввод-вывод будет лучше.
Других решений пока нет …