<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[vector&amp;lt;bool&amp;gt; serialisieren]]></title><description><![CDATA[<p>Ich habe ein vector&lt;bool&gt; mit ca. 2*10^11 Bits (also x64-Anwendung) und möchte dies daher möglichst rasch aus einer einzigen Datei xyz.dat serialisieren (in beide Richtungen), finde dazu nichts Brauchbares im Netz. Bietet C++ 11 hier etwas Raffiniertes? Die rechnerische Erzeugung der 200 Mrd. Bits benötigt z.Z. (single-threaded) noch 52 min., das Laden von Festplatte sollte also rascher erfolgen.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/333822/vector-lt-bool-gt-serialisieren</link><generator>RSS for Node</generator><lastBuildDate>Sun, 26 Apr 2026 08:58:20 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/333822.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 02 Aug 2015 21:39:53 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Sun, 02 Aug 2015 21:42:07 GMT]]></title><description><![CDATA[<p>Ich habe ein vector&lt;bool&gt; mit ca. 2*10^11 Bits (also x64-Anwendung) und möchte dies daher möglichst rasch aus einer einzigen Datei xyz.dat serialisieren (in beide Richtungen), finde dazu nichts Brauchbares im Netz. Bietet C++ 11 hier etwas Raffiniertes? Die rechnerische Erzeugung der 200 Mrd. Bits benötigt z.Z. (single-threaded) noch 52 min., das Laden von Festplatte sollte also rascher erfolgen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462158</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462158</guid><dc:creator><![CDATA[Erhard Henkes]]></dc:creator><pubDate>Sun, 02 Aug 2015 21:42:07 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Sun, 02 Aug 2015 22:00:39 GMT]]></title><description><![CDATA[<p>Also ~25GB Daten wenn ich richtig gerechnet habe? Für dein Problem ist mir nichts aus der STL bekannt und mich würde auch wundern wenn es dort sowas gibt. Also wirst wohl selbst immer 8 Bit nehmen müssen, zu einem Byte zusammen setzen und in eine Datei schreiben. Wird vermutlich nicht super schnell aber der Flaschenhals is vermutlich eh die Festplatte (außer du hast jetzt noch ein super schnelles Speichersystem). Brauchst du denn wirklich die Funktionalität von <code>vector&lt;bool&gt;</code> ? Ginge nicht auch ein <code>vector&lt;uint8_t&gt;</code> , wo du dir die Bit selbst raus ziehst wenn man gerade die Bit-Darstellung braucht?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462161</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462161</guid><dc:creator><![CDATA[sebi707]]></dc:creator><pubDate>Sun, 02 Aug 2015 22:00:39 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Sun, 02 Aug 2015 22:23:23 GMT]]></title><description><![CDATA[<p>Nein, unbedingt die bittable aus Effizienzgründen im Zugriff.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462164</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462164</guid><dc:creator><![CDATA[Erhard Henkes]]></dc:creator><pubDate>Sun, 02 Aug 2015 22:23:23 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Sun, 02 Aug 2015 22:48:46 GMT]]></title><description><![CDATA[<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /><br />
Bei solchen Mengen würde ich über Kompression nachdenken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462167</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462167</guid><dc:creator><![CDATA[5cript]]></dc:creator><pubDate>Sun, 02 Aug 2015 22:48:46 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Sun, 02 Aug 2015 23:06:07 GMT]]></title><description><![CDATA[<p>Das geht m.E. nicht, jedes Bit repräsentiert Primzahl ja/nein im Zahlenraum bis z.B. 2*10^11 (RAM-abhängig, passt zu 32 GB).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462169</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462169</guid><dc:creator><![CDATA[Erhard Henkes]]></dc:creator><pubDate>Sun, 02 Aug 2015 23:06:07 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Sun, 02 Aug 2015 23:20:09 GMT]]></title><description><![CDATA[<p>Bei solchen Mengen würde ich über die Benutzung der STXXL (Standard Template Library for Extra Large Data Sets) nachdenken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462171</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462171</guid><dc:creator><![CDATA[sws]]></dc:creator><pubDate>Sun, 02 Aug 2015 23:20:09 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 07:44:26 GMT]]></title><description><![CDATA[<p>Ist es dabei nicht eher problematisch dafür einen so so langen Speicherblock zu bekommen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462184</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462184</guid><dc:creator><![CDATA[blabla123456]]></dc:creator><pubDate>Mon, 03 Aug 2015 07:44:26 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 08:03:11 GMT]]></title><description><![CDATA[<p>Es gibt darauf keine Antwort, denn wie std::vector&lt;bool&gt; seine Daten ablegt ist implementationsspezifisch. Wenn du es fuer eine spezielle Implementation machen willst, ist es das einfachste den vector zu analysieren und dann mit fixen offsets und casts zu arbeiten. Oder eine eigene Implementation der Datenstruktur.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462188</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462188</guid><dc:creator><![CDATA[TGGC]]></dc:creator><pubDate>Mon, 03 Aug 2015 08:03:11 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 08:07:52 GMT]]></title><description><![CDATA[<p>Jo, selber implementieren und das underlying array als <code>char</code> -Array in eine Datei schieben. Am Besten mit den C-Funktionen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462190</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462190</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 03 Aug 2015 08:07:52 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 09:11:49 GMT]]></title><description><![CDATA[<p>Erhard Henkes schrieb:</p>
<blockquote>
<p>Nein, unbedingt die bittable aus Effizienzgründen im Zugriff.</p>
</blockquote>
<p>Wenn du Wert auf Effizenz legst, und mit derart vielen simpel strukturierten Daten hantieren musst, könnte sich eventuell lohnen, das Bitset als <em>Memory Mapped File</em> vorzuhalten. Boost bietet da was Portables (habe damit selbst allerdings noch keine Erfahrungen gesammelt):</p>
<p><a href="http://www.boost.org/doc/libs/1_58_0/libs/iostreams/doc/classes/mapped_file.html" rel="nofollow">http://www.boost.org/doc/libs/1_58_0/libs/iostreams/doc/classes/mapped_file.html</a></p>
<p>So eine Variante hätte ein paar Vorteile:</p>
<p>- Der User braucht nicht unbedingt 32GiB RAM, lediglich der virtuelle Addressraum sollte gross genug sein (also 64-Bit-Anwendung).<br />
- Laden/Speichern/Caching macht das Betriebssystem.<br />
- &quot;Zero Copy&quot; beim lesen/schreiben.<br />
- Datei ist wie zusammenhängeder Arbeitsspeicher addressierbar (via <code>char*</code> ).</p>
<p>Man könnte sogar so verwegen sein, und einen <code>std::vector&lt;bool&gt;</code> via placement <code>new</code> (und eigenem Allocator) in der Datei konstruieren. Ich würde allerdings wie Arcoth eher dazu raten, das selbst auf einem <code>char</code> -Array zu implementieren, damit man eine portable Datenstruktur hat. Ein <code>std::vector&lt;bool&gt;</code> würde dann nämlich auch das &quot;Dateiformat&quot; Implementations-Abhängig machen. D.h. man kann die Datei wahrscheinlich nur &quot;laden&quot;, wenn man exakt die selbe Standardbibliothek verwendet (und wenn man Pech hat müssen auch Compiler-Version/Flags, Debug/Release-Versionen der Standard-Lib, etc. übereinstimmen).</p>
<p>Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462199</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462199</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 03 Aug 2015 09:11:49 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 10:51:52 GMT]]></title><description><![CDATA[<blockquote>
<p>Das geht m.E. nicht, jedes Bit repräsentiert Primzahl ja/nein im Zahlenraum bis z.B. 2*10^11</p>
</blockquote>
<p>Versteh ich das richtig ?<br />
Du willst für die info ob ne Zahl von 0 - 2 * 10^11 ne Primzahl ist, in nem vector&lt;bool&gt; oder ähnliches speichern ?</p>
<p>ehrlich, wenn du den Speicher dafür nicht am Stück bekommst, bzw zwischenspeichern(platte) musst, geht dir jeglicher vorteil des Arrays verloren.<br />
200 * 10^9 &lt; 2^38<br />
für die bitmask brauchtest also 2^34 byte ^^<br />
16 GB nur für die Bitmask ?</p>
<p>Machts dann ned Sinn den lookup gleich auf nen Baum zu legen ?<br />
also in nen std::set&lt;int64_t&gt; und darauf bauen das der B-Baum lookup schneller ist also wie jegliches gerödel was brauchst um diese überdimensinale Bitmask zu verwalten ? Und dabei noch ne menge Speicher sparst (zumindest wenn die Primzahlen speicherst und nicht die &quot;nicht Primzahlen&quot; ^^)</p>
<p>Ciao ...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462208</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462208</guid><dc:creator><![CDATA[RHBaum]]></dc:creator><pubDate>Mon, 03 Aug 2015 10:51:52 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 11:09:46 GMT]]></title><description><![CDATA[<p>Ich habe mit einem std::unordered_set&lt;uint64_t&gt; begonnen (unordered_set hat etwas schnelleren find-Zugriff als set) und via File auf Platte ausgetauscht. Das braucht aber zuviel Speicher im RAM. Man kommt damit bei 32 GB RAM auf meinem PC bis in die Gegend von 5 Milliarden. Mit vector&lt;bool&gt; schafft man immerhin etwas mehr als 200 Mrd. (braucht 25 Mrd. byte).<br />
Hat mich auch verwundert.</p>
<p>Vgl.: <a href="http://www.michael-holzapfel.de/themen/primzahlen/pz-anzahl.htm" rel="nofollow">http://www.michael-holzapfel.de/themen/primzahlen/pz-anzahl.htm</a><br />
1.000.000.000 50.847.534<br />
10.000.000.000 455.052.511<br />
Mit 8 byte pro Primzahl kommt man da schnell hoch im RAM, da unordered_set einen gigantischen overhead besitzt). Vector&lt;bool&gt; dagegen ist heute wirklich &quot;lean&quot;. Dafür fehlt eine eingebaute Serialisierung (man kann die Bits nur als echte ASCII Zahlen in den Stream schieben).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462212</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462212</guid><dc:creator><![CDATA[Erhard Henkes]]></dc:creator><pubDate>Mon, 03 Aug 2015 11:09:46 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 11:09:57 GMT]]></title><description><![CDATA[<p>Bau dir doch nen Wrapper um nen vector&lt;char&gt;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462213</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462213</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Mon, 03 Aug 2015 11:09:57 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 11:28:41 GMT]]></title><description><![CDATA[<p>DocShoe schrieb:</p>
<blockquote>
<p>Bau dir doch nen Wrapper um nen vector&lt;char&gt;.</p>
</blockquote>
<p>Du meintest <code>vector&lt;uint8_t&gt;</code></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462216</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462216</guid><dc:creator><![CDATA[ftfy]]></dc:creator><pubDate>Mon, 03 Aug 2015 11:28:41 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 11:38:47 GMT]]></title><description><![CDATA[<p>RHBaum schrieb:</p>
<blockquote>
<p>Machts dann ned Sinn den lookup gleich auf nen Baum zu legen ?<br />
also in nen std::set&lt;int64_t&gt; und darauf bauen das der B-Baum lookup schneller ist also wie jegliches gerödel was brauchst um diese überdimensinale Bitmask zu verwalten ? Und dabei noch ne menge Speicher sparst (zumindest wenn die Primzahlen speicherst und nicht die &quot;nicht Primzahlen&quot; ^^)</p>
</blockquote>
<p>In dem Zahlenbereich kann man etwa zwischen 7 und 8 Milliarden Primzahlen erwarten. Selbst wenn man diese maximal speichereffizient in einer Dictionary-Datenstruktur untergebracht bekommt (also 8 Byte je Primzahl), dann benötigt man dafür schon etwa doppelt so viel Speicher wie für das Bitset. Wenn noch zusätzlicher Speicherbedarf für z.B. eine Baumstruktur hinzukommen, sieht es da wohl noch deutlich schlechter aus. Ich denke so ein Bitset ist schon eine ganz gute wahl für das spezifische Problem. Es hat ausserdem den Vorteil, dass man es für Einzelabfragen direkt adressieren kann. Das ist mindestens so gut wie eine Hash-Map, und muss auch nicht &quot;rödeln&quot; wenn das Bitset in einer Datei liegt. Für eine Einzelabfrage kann man direkt in O(1) an die richtige Dateiposition springen - im Gegensatz zum B-Baum, der dafür O(log(n)) Zugriffe braucht. Bei Bereichs-Abfragen (z.B. &quot;gib mir mal alle Primzahlen in [a, b]&quot;) <em>könnte</em> allerdings der Baum wieder glänzen.</p>
<p>Für Punkt-Abfragen würde ich aus dem Bauch heraus tippen, dass eine &quot;Memory Mapped&quot; Bitset nur schwer zu schlagen sein wird <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462217</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462217</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 03 Aug 2015 11:38:47 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 12:14:08 GMT]]></title><description><![CDATA[<blockquote>
<p>Ich denke so ein Bitset ist schon eine ganz gute wahl für das spezifische Problem.</p>
</blockquote>
<p>Ich weiß es, weil ich es vergleichend ausprobiert habe.</p>
<blockquote>
<p>&quot;Memory Mapped&quot; Bitset</p>
</blockquote>
<p>Kannst Du mir da einen Link auf ein Beispiel geben? Habe ich bisher noch nicht gebraucht. Klingt interessant für den Austausch mit dem File. Ansonsten baue ich mir wirklich einen wrapper um vector&lt;uint8_t&gt; oder vector&lt;uint64_t&gt; (weiß nicht, was schneller läuft).</p>
<pre><code>unordered_set&lt;uint64_t&gt; primzahlen; // so fing ich an 
fstream myPrimesDatabase;
uint64_t j;
myPrimesDatabase.open(&quot;myPrimesDatabase.dat&quot;, fstream::in | fstream::binary);
//cout &lt;&lt; &quot;Primzahlen werden aus der Datei geladen ...&quot; &lt;&lt; endl;
while (!myPrimesDatabase.eof())
{
  myPrimesDatabase.read((char*)&amp;j, sizeof(j));
  //cout &lt;&lt; j &lt;&lt; &quot; &quot;;
  primzahlen.insert(j);
}
myPrimesDatabase.close();
</code></pre>
<p>Bei 8 Byte muss man weniger read aufrufen als bei einem Byte Größe. Vielleicht sollte man das sogar für das read noch größer basteln mit einer wrapper-class. Kenne mich da nicht gut aus mit Optimieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462220</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462220</guid><dc:creator><![CDATA[Erhard Henkes]]></dc:creator><pubDate>Mon, 03 Aug 2015 12:14:08 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 12:54:15 GMT]]></title><description><![CDATA[<p>Normalerweise macht man dann eine reserve auf die Groesse und dann ein einziges read aus der Datei.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462225</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462225</guid><dc:creator><![CDATA[TGGC]]></dc:creator><pubDate>Mon, 03 Aug 2015 12:54:15 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 13:01:32 GMT]]></title><description><![CDATA[<p>TGGC schrieb:</p>
<blockquote>
<p>Normalerweise macht man dann eine reserve auf die Groesse und dann ein einziges read aus der Datei.</p>
</blockquote>
<p>Du meinst wohl resize. Außerdem hat das Beispiel gerade irgendwie gar nichts mehr mit Bitmasken zu tun. Wenn man dann einen vector&lt;uint8_t&gt; oder vector&lt;uint64_t&gt; hat kann man alles in einer read Anweisung laden, wie TGGC schon sagte. Noch ein Vorschlag um Platz zu sparen wenn du das nicht eh schon gemacht hast: Alle geraden Zahlen würde ich gar nicht in die Bitmaske aufnehmen. Dann braucht man nur die hälfte Speicherplatz und bei ~25GB die im RAM liegen/aus einer Datei geladen sollen wäre das schon sinnvoll.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462226</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462226</guid><dc:creator><![CDATA[sebi707]]></dc:creator><pubDate>Mon, 03 Aug 2015 13:01:32 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 13:08:35 GMT]]></title><description><![CDATA[<p>Erhard Henkes schrieb:</p>
<blockquote>
<blockquote>
<p>&quot;Memory Mapped&quot; Bitset</p>
</blockquote>
<p>Kannst Du mir da einen Link auf ein Beispiel geben? Habe ich bisher noch nicht gebraucht. Klingt interessant für den Austausch mit dem File. Ansonsten baue ich mir wirklich einen wrapper um vector&lt;uint8_t&gt; oder vector&lt;uint64_t&gt; (weiß nicht, was schneller läuft).</p>
</blockquote>
<p>Ich bezog mich damit auf meinen vorangenagenen Beitrag. Konkreten Beispiel-Code habe ich dafür leider nicht, nur den den Doku-Link aus der iostreams-Bibliothek von Boost, in der das &quot;Memory Mapping&quot; für Dateien portabel implementiert ist:</p>
<p><a href="http://www.boost.org/doc/libs/1_58_0/libs/iostreams/doc/classes/mapped_file.html" rel="nofollow">http://www.boost.org/doc/libs/1_58_0/libs/iostreams/doc/classes/mapped_file.html</a></p>
<p>Das Ganze setzt also voraus, dass du ein wenig experimentierfreudig bist und die Muße hast dich durch die Doku zu arbeiten - der Dateizugriff läuft dabei etwas anders als das klassische open/read/write ab, und es ist nicht Teil der Standardbibliothek - du brauchst also Boost dafür <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Nur für den Fall, dass dir nicht ganz klar sein sollte, was es mit dem &quot;Memory Mapping&quot; auf sich hat:<br />
Es handelt sich dabei um eine die Betriebssystem-Funktion, die auch bei Auslagerungsdateien/Swapspeicher zum Einsatz kommt. Dabei wird eine Datei in den Virtuellen Addressraum (also den &quot;RAM&quot;) &quot;abgebildet&quot;. Der Zugriff auf den Dateiinhalt erfolgt dabei über einen simplen <code>char*</code> (siehe <code>boost::iostreams::mapped_file::data()</code> ), der auf einen Speicherbereich von der Größe der gemappten Datei zeigt. Das Lesen/Schreiben der Daten wird dabei transparent vom Betriebssystem übernommen (inklusive effizentem Caching der Daten). Das einzige was man dabei selbst macht, ist in den Speicherbereich auf den der <code>char*</code> zeigt zu schreiben bzw. davon zu lesen (bzw. darin deine Bits zu &quot;schubsen&quot;). Speicherseiten, die nicht im physischen RAM vorliegen, werden dabei vom OS aus der Datei geladen, und gleichzeitig Seiten aus dem physischen Speicher in die Datei &quot;ausgelagert&quot;, bzw. zurückgeschrieben.</p>
<p>Ich habe wie schonmal erwähnt selbst noch nicht mit <code>mapped_file</code> gearbeitet, deswegen die Warnung von wegen &quot;experimentierfreudig&quot;. Ich denke aber, dass das für deine Datenmassen ein schöner Anwendungsfall für ein solches Memory Mapping sind:<br />
Deine Datenstruktur ist simpel genug, um sie mal eben &quot;roh&quot; in einen <code>char*</code> &quot;reinschreiben&quot; zu können, und es gibt dir mit überschaubarem Aufwand die Flexibilität, die Daten dank OS eben nicht alle im physischen Arbeitsspeicher vorhalten zu müssen.<br />
Dennoch kann man mit den Daten arbeiten, als lägen sie dort.</p>
<p>Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462227</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462227</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 03 Aug 2015 13:08:35 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 20:35:37 GMT]]></title><description><![CDATA[<blockquote>
<p>Alle geraden Zahlen würde ich gar nicht in die Bitmaske aufnehmen.</p>
</blockquote>
<p>Super Idee!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462310</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462310</guid><dc:creator><![CDATA[Erhard Henkes]]></dc:creator><pubDate>Mon, 03 Aug 2015 20:35:37 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 20:40:05 GMT]]></title><description><![CDATA[<p>Erhard Henkes schrieb:</p>
<blockquote>
<blockquote>
<p>Alle geraden Zahlen würde ich gar nicht in die Bitmaske aufnehmen.</p>
</blockquote>
<p>Super Idee!</p>
</blockquote>
<p>Genausowenig die Zahlen, die durch 3 teilbar sind.</p>
<p>Der Index für n ist dann n-n/2-n/3+n/6.</p>
<p>Und dann natürlich auch für 5, 7, 11 und 13, musst von Hand schauen, wann aufhören.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462313</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462313</guid><dc:creator><![CDATA[andrepeat]]></dc:creator><pubDate>Mon, 03 Aug 2015 20:40:05 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 22:24:16 GMT]]></title><description><![CDATA[<p>Hi nochmal!</p>
<p>Da ich mich schon länger mal mit <em>Memory Mapped IO</em> beschäftigen wollte, habe ich mir zum Feierabend mal die Zeit genommen und einen Prototypen für das von mir vorgeschlagene Bitset implementiert. Wer möchte, kann den Code gerne verwenden/erweitern/reviewen/sich inspirieren lassen oder was auch immer. War ne nette Übung um mal was mit Memory Mapping abseits von GPU-Hardware herumzuspielen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Das Interface orientiert sich größtenteils an <code>std::bitset</code> , und die Klasse sollte bis auf Details nahezu als Drop-In Replacement einsetzbar sein, wenn man mal ganz furchtbar viele Flags benötigen sollte :p.<br />
Natürlich stecken wahrscheinlich noch eine Reihe Fehler drin - extrem grob falsch wird es allerdings hoffentlich nicht sein <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>Auch wenn ich nur einen simplen Zeittest gemacht habe, scheint die Klasse im linearen Schreiben/Lesen durchaus mit einem <code>std::vector&lt;bool&gt;</code> im Arbeitsspeicher mithalten zu können (siehe Testcode), obwohl die Datenstruktur in eine Datei ausgelagert ist. Der Testcode erstellt die Datenstruktur mit jeweils 10 Milliarden Bits, schreibt alle davon linear und liest sie anschliessend ebenfalls linear. Auf meiner Mühle - Windows 8.1 - kompiliert mit Visual C++ 2013 mit Optimierungen im Release-Modus sieht das ganze etwa so aus:</p>
<pre><code>MemoryMappedBitset:     92.6532 Sekunden (Code siehe unten).
std::vector&lt;bool&gt;:      98.7792 Sekunden (1).
std::bitset (im Heap): 115.5720 Sekunden (2).
</code></pre>
<p>1: <a href="http://pastebin.com/R3sDkhb6" rel="nofollow">http://pastebin.com/R3sDkhb6</a><br />
2: <a href="http://pastebin.com/egdsRTtM" rel="nofollow">http://pastebin.com/egdsRTtM</a></p>
<p>Ob sich so eine dateigestützte Datenstruktur wirklich lohnt, sollte man allerdings individuell mit realistischen Zugriffsmustern austesten. Gut möglich, dass das Teil bei mehr &quot;Random Access&quot; noch deutlich absackt. Einen Vorteil hat sie allerdings:<br />
Man muss sich keinen Kopf um den physichen RAM und das nachladen/wegschreiben der Daten machen - Das Testprogramm lümmelt hier bei mir mit 300KiB im Arbeitsspeicher rum - genutzt wird de facto nur der freie Systemspeicher, den das OS grad entbehren kann.</p>
<p>Gruss,<br />
Finnegan</p>
<p>P.S.: Ja, Kommentare sind rar, ich hoffe der Code ist simpel genug dass sich die Funktionsweise aus dem Code erschließt (siehe auch Boost-Doku zu <code>mapped_file</code> ). Mit dem <code>create</code> -Parameter des Konstruktors wird angegeben, ob eine neue Datei erstellt (überschreibt existierende) oder eine vorhandene Datei verwendet werden soll.</p>
<pre><code>#include &lt;cstdint&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;chrono&gt;
#include &lt;boost/filesystem.hpp&gt;
#include &lt;boost/iostreams/device/mapped_file.hpp&gt;

class MemoryMappedBitset
{
    using mapped_file = boost::iostreams::mapped_file;
    using mapped_file_params = boost::iostreams::mapped_file_params;
    public:
        class reference
        {
            friend class MemoryMappedBitset;
            public:
                void flip();

                reference&amp; operator=(bool value);
                reference&amp; operator=(const reference&amp; other);
                operator bool() const;
                bool operator~() const;

            private:
                MemoryMappedBitset&amp; bitset;
                std::size_t         pos;

                reference(MemoryMappedBitset&amp; bitset, std::size_t pos);
        };

        MemoryMappedBitset(const MemoryMappedBitset&amp;) = delete;
        MemoryMappedBitset&amp; operator=(const MemoryMappedBitset&amp;) = delete;

        MemoryMappedBitset(std::string file_name);
        MemoryMappedBitset(std::string file_name, std::size_t number_of_bits, bool create = false);
        ~MemoryMappedBitset();

        const std::string&amp; getFileName() const;
        std::size_t size() const;
        bool test(std::size_t pos);
        void set(std::size_t pos, bool value = true);
        void reset(std::size_t pos);
        void flip(std::size_t pos);

        bool operator[](std::size_t pos) const;
        reference operator[](std::size_t pos);

    private:
        mapped_file_params  params;
        mapped_file         file;
        std::size_t         number_of_bits;
        unsigned char*      data;

        bool testUnchecked(std::size_t pos) const;
        void setUnchecked(std::size_t pos, bool value);
        void flipUnchecked(std::size_t pos);
};

MemoryMappedBitset::reference::reference(MemoryMappedBitset&amp; bitset, std::size_t pos)
: bitset(bitset), pos(pos)
{
}

void MemoryMappedBitset::reference::flip()
{
    bitset.flipUnchecked(pos);
}

MemoryMappedBitset::reference&amp; MemoryMappedBitset::reference::operator=(bool value)
{
    bitset.setUnchecked(pos, value);
    return *this;
}

MemoryMappedBitset::reference&amp; MemoryMappedBitset::reference::operator=(const reference&amp; other)
{
    bitset.setUnchecked(pos, other);
    return *this;
}

MemoryMappedBitset::reference::operator bool() const
{
    return bitset.testUnchecked(pos);
}

bool MemoryMappedBitset::reference::operator~() const
{
    return !bitset.testUnchecked(pos);
}

MemoryMappedBitset::MemoryMappedBitset(std::string file_name)
: MemoryMappedBitset(std::move(file_name), 0, false)
{
}

MemoryMappedBitset::MemoryMappedBitset(std::string file_name, std::size_t number_of_bits, bool create)
: data(nullptr)
{
    params.path = std::move(file_name);
    params.mode = std::ios_base::binary | std::ios_base::in | std::ios_base::out;

    // Size of the memory map in bytes.
    std::size_t map_size = number_of_bits / 8;
    // One extra byte for additional bits.
    if (number_of_bits % 8 &gt; 0)
        map_size += 1;
    // Map size must be multiple of (OS) page alignment.
    std::size_t non_aligned = map_size % mapped_file::alignment();
    if (non_aligned &gt; 0)
        map_size += mapped_file::alignment() - non_aligned;

    // Create new (overwrite) or re-use file.
    if (create)
    {
        params.new_file_size = map_size;
        params.length = map_size;
    }
    else
    {
        // Map requested number of bits unless file is not large enough.
        map_size = std::min(static_cast&lt;std::uintmax_t&gt;(map_size), boost::filesystem::file_size(params.path));
        // Ensure that map size is still multiple of (OS) page alignment 
        // (if file size was not) and not larger than file size.
        non_aligned = map_size % mapped_file::alignment();
        if (non_aligned &gt; 0)
             map_size -= non_aligned;

        params.new_file_size = 0;
        params.length = map_size;
    }

    // Set actual number of bits. This is at least the requested number of bits
    // unless we re-used an existing file which was not large enough.
    MemoryMappedBitset::number_of_bits = map_size * 8;

    file.open(params);
    data = reinterpret_cast&lt;unsigned char*&gt;(file.data());
    assert(data != nullptr);
}

MemoryMappedBitset::~MemoryMappedBitset()
{
    if (file.is_open())
        file.close();
}

const std::string&amp; MemoryMappedBitset::getFileName() const
{
    return params.path;
}

std::size_t MemoryMappedBitset::size() const
{
    return number_of_bits;
}

bool MemoryMappedBitset::test(std::size_t pos)
{
    if (pos &gt;= size())
        throw std::out_of_range(&quot;Bit position out of range.&quot;);

    return testUnchecked(pos);
}

void MemoryMappedBitset::set(std::size_t pos, bool value)
{
    if (pos &gt;= size())
        throw std::out_of_range(&quot;Bit position out of range.&quot;);

    setUnchecked(pos, value);
}

void MemoryMappedBitset::reset(std::size_t pos)
{
    set(pos, false);
}

void MemoryMappedBitset::flip(std::size_t pos)
{
    if (pos &gt;= size())
        throw std::out_of_range(&quot;Bit position out of range.&quot;);

    flipUnchecked(pos);
}

bool MemoryMappedBitset::operator[](std::size_t pos) const
{
    return testUnchecked(pos);
}

MemoryMappedBitset::reference MemoryMappedBitset::operator[](std::size_t pos)
{
    return reference(*this, pos);
}

bool MemoryMappedBitset::testUnchecked(std::size_t pos) const
{
    return (data[pos / 8] &amp; (1 &lt;&lt; (pos % 8))) != 0;
}

void MemoryMappedBitset::setUnchecked(std::size_t pos, bool value)
{
    std::size_t index = pos / 8;
    std::size_t bit = pos % 8;
    if (value)
        data[index] |= 1 &lt;&lt; bit;
    else
        data[index] &amp;= ~(1 &lt;&lt; bit);
}

void MemoryMappedBitset::flipUnchecked(std::size_t pos)
{
    data[pos / 8] ^= 1 &lt;&lt; (pos % 8);
}

int main()
{
    const std::size_t number_of_bits = 10000000000;
    const std::uint32_t test_pattern = 0xaaaaaaaa;
    const std::uint32_t use_pattern_bits = 7;

    auto start_time = std::chrono::high_resolution_clock::now();

    try
    {
        std::cout &lt;&lt; &quot;Erstelle Bitset mit &quot; &lt;&lt; number_of_bits &lt;&lt; &quot; Bits ...&quot; &lt;&lt; std::endl;
        MemoryMappedBitset mbs(&quot;bitset.dat&quot;, number_of_bits, true);

        std::cout &lt;&lt; &quot;Schreibe Bits ...&quot;;
        for (std::size_t i = 0; i &lt; number_of_bits; ++i)
        {
            mbs[i] = (test_pattern &amp; (1 &lt;&lt; (i % use_pattern_bits))) != 0;
            if (i % (number_of_bits / 100) == 0)
                std::cout &lt;&lt; &quot;.&quot;;
        }

        std::cout &lt;&lt; &quot;\nLese Bits ...&quot;;
        std::uint32_t value = 0;
        for (std::size_t i = 0; i &lt; number_of_bits; ++i)
        {
            std::uint32_t shift = (i % use_pattern_bits);
            value |= mbs[i] &lt;&lt; shift;
            if (shift == use_pattern_bits - 1)
            {
                assert(value == (test_pattern &amp; (1 &lt;&lt; use_pattern_bits) - 1));
                value = 0;
            }
            if (i % (number_of_bits / 100) == 0)
                std::cout &lt;&lt; &quot;.&quot;;
        }

        std::cout &lt;&lt; &quot;\nfertig!&quot; &lt;&lt; std::endl;

    }
    catch (const std::exception&amp; e)
    {
        std::cout &lt;&lt; &quot;ERROR: &quot; &lt;&lt; e.what() &lt;&lt; std::endl;    	
    }

    std::cout &lt;&lt; std::chrono::duration&lt;double&gt;(
        std::chrono::high_resolution_clock::now() - start_time).count() &lt;&lt; &quot; Sekunden.&quot; &lt;&lt; std::endl;
}
</code></pre>
<p>Code benötigt <a href="http://www.boost.org/" rel="nofollow">Boost</a> und muss gegen <code>boost_filesystem</code> , <code>boost_system</code> und <code>boost_iostreams</code> gelinkt werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462314</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462314</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 03 Aug 2015 22:24:16 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 20:54:39 GMT]]></title><description><![CDATA[<p>Finnegan schrieb:</p>
<blockquote>
<pre><code class="language-cpp">char*               data;
</code></pre>
</blockquote>
<p>Ich würde das auf unsigned char ändern, auch wenn du dann einmal casten musst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462316</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462316</guid><dc:creator><![CDATA[ubbot]]></dc:creator><pubDate>Mon, 03 Aug 2015 20:54:39 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Mon, 03 Aug 2015 21:09:31 GMT]]></title><description><![CDATA[<p>ubbot schrieb:</p>
<blockquote>
<p>würde das auf unsigned char ändern, auch wenn du dann einmal casten musst.</p>
</blockquote>
<p>Gern. Die mag ich auch lieber wenn ich mit Bits hantiere. Ist halt das was man von Boost bekommt...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462319</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462319</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 03 Aug 2015 21:09:31 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Tue, 04 Aug 2015 01:29:09 GMT]]></title><description><![CDATA[<p>andrepeat schrieb:</p>
<blockquote>
<p>Erhard Henkes schrieb:</p>
<blockquote>
<blockquote>
<p>Alle geraden Zahlen würde ich gar nicht in die Bitmaske aufnehmen.</p>
</blockquote>
<p>Super Idee!</p>
</blockquote>
<p>Genausowenig die Zahlen, die durch 3 teilbar sind.</p>
<p>Der Index für n ist dann n-n/2-n/3+n/6.</p>
<p>Und dann natürlich auch für 5, 7, 11 und 13, musst von Hand schauen, wann aufhören.</p>
</blockquote>
<p>Da gibt es, finde ich, ein natürliches Optimum: 2,3und5 nehmen.<br />
Rechnet man eine Zahl modulo 30, gibt es 8 mögliche Divisionsreste, die Primzahlen erlauben. Und 8 Bit hat ein Byte, wodurch der Zugriff ganz geschmeidig bleibt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462330</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462330</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 04 Aug 2015 01:29:09 GMT</pubDate></item><item><title><![CDATA[Reply to vector&amp;lt;bool&amp;gt; serialisieren on Tue, 04 Aug 2015 06:35:38 GMT]]></title><description><![CDATA[<p>First rule of IOB: You are wrong.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2462343</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2462343</guid><dc:creator><![CDATA[TGGC]]></dc:creator><pubDate>Tue, 04 Aug 2015 06:35:38 GMT</pubDate></item></channel></rss>