Große Zahlenlisten in C++
Teilnehmerfrage: Wie kann man Zahlenlisten mit Milliarden von Zahlen in C++ verarbeiten?
main.cpp
#include <iostream>
#include <ostream>
#include <deque>
#include <locale>
#include <iomanip> int main()
{ struct with_grouping : ::std::numpunct< char >
{ protected:
virtual char do_thousands_sep () const override { return '.'; }
virtual ::std::string do_grouping () const override { return "\03\03"; }};
with_grouping with_grouping{};
::std::cout.imbue( ::std::locale( ::std::cout.getloc(), &with_grouping ) ) ;
::std::deque< char >d; unsigned long long l;
try{ for( l = 0;; ++l )d.push_back( 0 ); }
catch( ... ){ ::std::cout << "l = " << l << "\n"; }}::std::cout
l = 2.044.339.711
main.cpp
#include <iostream> /* ::std::cerr */
#include <ostream> /* << */
#include <new> /* ::std::set_new_handler */
#include <deque> /* ::std::deque */
#include <cstddef> /* ::std::abort */ unsigned long long l = -1; void f(){ ::std::cerr << l << '\n'; ::std::abort(); } int main(){ ::std::set_new_handler( f );
::std::deque< char >d; for( l = 0;; ++l )d.push_back( 0 ); }
- Rückfrage: Was soll damit gemacht werden? Woher kommen so viele Zahlen? In welchem Format liegen sie vor? Handelt es sich vielleicht um dünnbesetzte Matrizen (sparse matrices ?)
- Die Standardlösung ist zunächst, ein 64-Bit-Betriebssystem mit ausreichend viel Speicher auszustatten, da Speicher billiger ist als die Arbeitszeit von Programmierern. Ein 64-Bit-Betriebssystem erlaubt es 2014 oft, zirka ( 2 hoch 48 )Oktette (=262 Tebioktett) zu adressieren.
- Die Anzahl der Informationen, die im Hauptspeicher gehalten werden können, ist nur bedingt eine Frage der Programmiersprache, da sie zunächst durch die Größe des Speichers vorgegeben ist. Mit C oder C++ kann die vorhandene Hardware aber oft besonders gut ausgenutzt werden, eventuell kommen aber auch spezielle Sprachen zur effizienten Verarbeitung großer Matrizen (wie MATLAB) in Frage.
- In manchen Fällen kann es passend sein, die Zahlen in einer Datei oder einer Datenbank zu halten und nicht alle gleichzeitig in den Hauptspeicher zu laden.
- Reihungen mit statischer oder automatischer Lebensdauer dürfen oft nicht groß sein. Bei automatischer Lebensdauer sind oft nur einige Mebioktett möglich. sie müssen daher mit dynamischer Lebensdauer angefordert werden (»double * p = new double[ 9 ];«), Hierzu muß aber erst mehr über new[] und delete[] gelernt werden
- Reihungen, ::std::array, und ::std::vector benötigen den Speicher in einem Stück, bei Fragmentation kann daher ::std::deque noch mehr Daten aufnahmen
- speicherplatzsparende Gleitkommatypen: float
- speicherplatzsparende ganzzahlige Typen: short, unsigned short, char
- Speicher = physikalischer Speicher und Auslagerungsspeicher
- Die Verarbeitung von vielen Zahlen kann auch langsam werden, die Optimierung ist großes Thema für sich. Hilfreich ist es jedoch, wenn aufeinanderfolgende Speicherzugriffe möglichst nahe beieinander liegen und die Daten überhaupt alle im physikalischen Hauptspeicher liegen
- Falls extrem große Datenmengen sehr schnell verarbeitet sollen, sind manchmal aufwendige Lösungen nötig, bei denen Hardware und das Betriebssystem (gegen Fragmentierung) speziell dafür angepaßt werden.
- fread/fwrite kann schneller sein als formatierte Ein-/Ausgabe, ist aber weniger portabel. memory-mapped files sind nicht immer schneller.
- http://en.wikipedia.org/wiki/List_of_numerical_libraries#C.2B.2B