Durante il tentativo di utilizzare i file mappati in memoria per creare un file da più gigabyte (circa 13gb), mi sono imbattuto in quello che sembra essere un problema con mmap(). L'implementazione iniziale è stata eseguita in C++ su Windows usando boost :: iostreams :: mapped_file_sink e tutto andava bene. Il codice è stato quindi eseguito su Linux e ciò che ha richiesto minuti su Windows è diventato ore su Linux.Prestazioni di file mappati in memoria male di Linux con accesso casuale C++ e Python
Le due macchine sono cloni dello stesso hardware: Dell R510 2,4 GHz 8 M Cache 16 GB Ram 1TB Disco PERC H200 Controller.
Linux è Oracle Enterprise Linux 6.5 che utilizza il kernel 3.8 e g ++ 4.83.
C'era qualche preoccupazione che potesse esserci un problema con la libreria boost, quindi le implementazioni sono state eseguite con boost :: interprocess :: file_mapping e di nuovo con nativo mmap(). Tutti e tre mostrano lo stesso comportamento. Le prestazioni di Windows e Linux sono pari a un certo punto quando le prestazioni di Linux diminuiscono.
Il codice sorgente completo ei numeri delle prestazioni sono collegati di seguito.
// C++ code using boost::iostreams
void IostreamsMapping(size_t rowCount)
{
std::string outputFileName = "IoStreamsMapping.out";
boost::iostreams::mapped_file_params params(outputFileName);
params.new_file_size = static_cast<boost::iostreams::stream_offset>(sizeof(uint64_t) * rowCount);
boost::iostreams::mapped_file_sink fileSink(params); // NOTE: using this form of the constructor will take care of creating and sizing the file.
uint64_t* dest = reinterpret_cast<uint64_t*>(fileSink.data());
DoMapping(dest, rowCount);
}
void DoMapping(uint64_t* dest, size_t rowCount)
{
inputStream->seekg(0, std::ios::beg);
uint32_t index, value;
for (size_t i = 0; i<rowCount; ++i)
{
inputStream->read(reinterpret_cast<char*>(&index), static_cast<std::streamsize>(sizeof(uint32_t)));
inputStream->read(reinterpret_cast<char*>(&value), static_cast<std::streamsize>(sizeof(uint32_t)));
dest[index] = value;
}
}
Un test finale è stato eseguito in Python per riprodurlo in un'altra lingua. La caduta è avvenuta nello stesso posto, quindi sembra lo stesso problema.
# Python code using numpy
import numpy as np
fpr = np.memmap(inputFile, dtype='uint32', mode='r', shape=(count*2))
out = np.memmap(outputFile, dtype='uint64', mode='w+', shape=(count))
print("writing output")
out[fpr[::2]]=fpr[::2]
per il C++ test Windows e Linux hanno simili prestazioni fino a circa 300 milioni di int64s (con Linux guardando un po 'più veloce). Sembra che le prestazioni cadano su Linux attorno a 3Gb (400 milioni * 8 byte per int64 = 3.2Gb) sia per C++ che per Python.
So su Linux a 32 bit che 3Gb è un limite magico, ma non sono a conoscenza di un comportamento simile per Linux a 64 bit.
L'essenza dei risultati è di 1,4 minuti per Windows che diventa 1,7 ore su Linux a 400 milioni di int64. In realtà sto provando a mappare circa 1,3 miliardi di int64s.
Qualcuno può spiegare perché c'è una tale disconnessione nelle prestazioni tra Windows e Linux?
Qualsiasi aiuto o suggerimento sarebbe molto apprezzato!
Updated Results Con codice Python aggiornato ... velocità Python attualmente comparabili con C++
Original Results NOTA: I risultati Python sono stantio
Quanta memoria hai in la tua macchina Linux? –
@MatsPetersson 16 GB Ram –
Puoi provare a usare madvise() e vedere se cambia qualcosa? Potrebbe essere necessario provare vari parametri di consulenza: http://man7.org/linux/man-pages/man2/madvise.2.html –