<?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[Funktion schneller machen]]></title><description><![CDATA[<p>Abend!</p>
<p>Ich habe in meiner 3D-Anwendung eine Funktion, die sehr oft aufgerufen wird (in jedem Frame einmal) und die leider zu langsam ist. Wenn ich die Funktion rausnehme, habe ich ca 800fps, wenn ich sie reinnehme bricht die Performance ein auf ca 30 fps. Die Funktion sieht so aus:</p>
<pre><code class="language-cpp">void ModifyHeightAction::addVertices(const std::vector&lt;VertexIndexAndHeightPair&gt;&amp; verts) {
   VertexMapIterator iter;

   VertexIndexAndHeightPair vert;
   Index i;
   Heights h;

   std::vector&lt;VertexIndexAndHeightPair&gt;::const_iterator it	= verts.begin();
   std::vector&lt;VertexIndexAndHeightPair&gt;::const_iterator itEnd	= verts.end();
   for(; it != itEnd; ++it) {
      i.row = it-&gt;vertexRow;
      i.col = it-&gt;vertexCol;
      iter = mVertexMap.find(i);   // mVertexMap ist vom Typ std::map&lt;Index, Heights&gt;

      if(iter == mVertexMap.end()) {
         h.initial = it-&gt;initialHeight;
         h.modified = it-&gt;modifiedHeight;
         mVertexMap[i] = h;
      }
      else {
         iter-&gt;second.modified = it-&gt;modifiedHeight;
      }
   }
}
// Das hier sind alle beteiligten Strukturen:
// Index/Höhen Pärchen
struct VertexIndexAndHeightPair {
   int  vertexRow, vertexCol;	
   float initialHeight, modifiedHeight;		
};

struct Index { int row, col; };

bool operator&lt;(const Index&amp; lhs, const Index&amp; rhs) {
   if(lhs.row &lt; rhs.row)
      return true;
   else if(lhs.row &gt; rhs.row)
      return false;
   return lhs.col &lt; rhs.col;
}

struct Heights { float initial, modified; };
</code></pre>
<p>Die Funktion kriegt einen vector mit Strukturen, die ein Index/Höhen Pärchen darstellen. Was die Funktion jetzt machen soll ist sehr simpel: Die Klasse ModifyHeightAction hat eine std::map namens mVertexMap als Member (der Typ ist in Zeile 13 dargestellt). Die Funktion soll jetzt über alle Elemente des Eingabevektors gehen und wenn die Map noch kein Element mit diesem Index besitzt, soll ein Eintrag in die Map geschrieben werden (Key = Index, Value = die 2 Höhen). Befindet sich bereits ein Element mit diesem Index in der Map, soll nur der 2. Höhenwert (namens modified) geupdated werden. Es ist völlig egal ob die Keys sortiert sind. Es geht mir nur darum, dass jeder Index maximal 1mal in der Map ist (und wenn der selbe Index erneut im Vektor erscheint eben modified angepasst wird).</p>
<p>Wie ich es implementiert habe seht ihr ja im Code. Ich gehe mit einem Iterator über den vector, suche in der Map nach dem Index (des Elements, auf den der Iterator gerade zeigt) und wenn er noch nicht in der Map ist, füge ich das Höhenpärchen in die Map ein.</p>
<p>Lustigerweise scheint das find() garnicht der Flaschenhals zu sein, sondern das Einfügen in die Map in Zeile 18, also: mVertexMap[i] = h;<br />
Allerdings weiß ich nicht, wie ich das beschleunigen sollte?</p>
<p>Hat irgendwer eine Idee, wie ich die Funktion schneller implementieren könnte? Vllt ein anderer Algo oder eine andere Datenstruktur oder..?</p>
<p>Danke!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/251332/funktion-schneller-machen</link><generator>RSS for Node</generator><lastBuildDate>Tue, 15 Sep 2026 13:31:17 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/251332.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 03 Oct 2009 00:10:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 00:10:28 GMT]]></title><description><![CDATA[<p>Abend!</p>
<p>Ich habe in meiner 3D-Anwendung eine Funktion, die sehr oft aufgerufen wird (in jedem Frame einmal) und die leider zu langsam ist. Wenn ich die Funktion rausnehme, habe ich ca 800fps, wenn ich sie reinnehme bricht die Performance ein auf ca 30 fps. Die Funktion sieht so aus:</p>
<pre><code class="language-cpp">void ModifyHeightAction::addVertices(const std::vector&lt;VertexIndexAndHeightPair&gt;&amp; verts) {
   VertexMapIterator iter;

   VertexIndexAndHeightPair vert;
   Index i;
   Heights h;

   std::vector&lt;VertexIndexAndHeightPair&gt;::const_iterator it	= verts.begin();
   std::vector&lt;VertexIndexAndHeightPair&gt;::const_iterator itEnd	= verts.end();
   for(; it != itEnd; ++it) {
      i.row = it-&gt;vertexRow;
      i.col = it-&gt;vertexCol;
      iter = mVertexMap.find(i);   // mVertexMap ist vom Typ std::map&lt;Index, Heights&gt;

      if(iter == mVertexMap.end()) {
         h.initial = it-&gt;initialHeight;
         h.modified = it-&gt;modifiedHeight;
         mVertexMap[i] = h;
      }
      else {
         iter-&gt;second.modified = it-&gt;modifiedHeight;
      }
   }
}
// Das hier sind alle beteiligten Strukturen:
// Index/Höhen Pärchen
struct VertexIndexAndHeightPair {
   int  vertexRow, vertexCol;	
   float initialHeight, modifiedHeight;		
};

struct Index { int row, col; };

bool operator&lt;(const Index&amp; lhs, const Index&amp; rhs) {
   if(lhs.row &lt; rhs.row)
      return true;
   else if(lhs.row &gt; rhs.row)
      return false;
   return lhs.col &lt; rhs.col;
}

struct Heights { float initial, modified; };
</code></pre>
<p>Die Funktion kriegt einen vector mit Strukturen, die ein Index/Höhen Pärchen darstellen. Was die Funktion jetzt machen soll ist sehr simpel: Die Klasse ModifyHeightAction hat eine std::map namens mVertexMap als Member (der Typ ist in Zeile 13 dargestellt). Die Funktion soll jetzt über alle Elemente des Eingabevektors gehen und wenn die Map noch kein Element mit diesem Index besitzt, soll ein Eintrag in die Map geschrieben werden (Key = Index, Value = die 2 Höhen). Befindet sich bereits ein Element mit diesem Index in der Map, soll nur der 2. Höhenwert (namens modified) geupdated werden. Es ist völlig egal ob die Keys sortiert sind. Es geht mir nur darum, dass jeder Index maximal 1mal in der Map ist (und wenn der selbe Index erneut im Vektor erscheint eben modified angepasst wird).</p>
<p>Wie ich es implementiert habe seht ihr ja im Code. Ich gehe mit einem Iterator über den vector, suche in der Map nach dem Index (des Elements, auf den der Iterator gerade zeigt) und wenn er noch nicht in der Map ist, füge ich das Höhenpärchen in die Map ein.</p>
<p>Lustigerweise scheint das find() garnicht der Flaschenhals zu sein, sondern das Einfügen in die Map in Zeile 18, also: mVertexMap[i] = h;<br />
Allerdings weiß ich nicht, wie ich das beschleunigen sollte?</p>
<p>Hat irgendwer eine Idee, wie ich die Funktion schneller implementieren könnte? Vllt ein anderer Algo oder eine andere Datenstruktur oder..?</p>
<p>Danke!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787529</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787529</guid><dc:creator><![CDATA[marcD22]]></dc:creator><pubDate>Sat, 03 Oct 2009 00:10:28 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 00:50:50 GMT]]></title><description><![CDATA[<p>Die Geschichte schaut vom Design her schon sehr ineffizient aus. Dass du überhaupt die Struktur so zerlegen musst.</p>
<p>Aber als einfache Lösung könntest du <a href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00596.html" rel="nofollow">std::(tr1::)unordered_map</a> anstelle von <code>std::map</code> probieren. Und <code>insert</code> und nicht <code>map[n] = h;</code> zum einfügen benutzen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787533</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787533</guid><dc:creator><![CDATA[rüdiger]]></dc:creator><pubDate>Sat, 03 Oct 2009 00:50:50 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 01:09:16 GMT]]></title><description><![CDATA[<p>Zum Design: Naja, ich hatte ursprünglich ein &quot;simpleres&quot; Design. Als Zieldatenstruktur hatte ich statt einer std::map einfach einen std::vector&lt;VertexIndexAndHeightPair&gt;. Das hinzufügen (mit push_back) war natürlich sehr schnell, nur war die Suche mittels find(), ob der Index bereits in dem vector ist unglaublich langsam. Nur deshalb habe ich auf eine map umgestellt und es ist auch bereits deutlich schneller, aber noch immer nicht schnell genug :|</p>
<p>Zu der unordered_map: Muss ich mir da eine eigene Hash Funktion für Index schreiben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787535</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787535</guid><dc:creator><![CDATA[marcD22]]></dc:creator><pubDate>Sat, 03 Oct 2009 01:09:16 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 01:53:14 GMT]]></title><description><![CDATA[<p>marcD22 schrieb:</p>
<blockquote>
<p>Abend!</p>
<p>Ich habe in meiner 3D-Anwendung eine Funktion, die sehr oft aufgerufen wird (in jedem Frame einmal)</p>
</blockquote>
<p>Warum? Du must doch deine mVertexMap nur updaten, wenn sich was ändert. Und dann auch nur das was sich ändert. Übrigens Release kompilierst du schon, oder?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787539</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787539</guid><dc:creator><![CDATA[preoptimal]]></dc:creator><pubDate>Sat, 03 Oct 2009 01:53:14 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 03:19:30 GMT]]></title><description><![CDATA[<p>preoptimal schrieb:</p>
<blockquote>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Abend!</p>
<p>Ich habe in meiner 3D-Anwendung eine Funktion, die sehr oft aufgerufen wird (in jedem Frame einmal)</p>
</blockquote>
<p>Warum? Du must doch deine mVertexMap nur updaten, wenn sich was ändert. Und dann auch nur das was sich ändert. Übrigens Release kompilierst du schon, oder?</p>
</blockquote>
<p>Keine Sorge, ich weiß schon wann ich sie aufrufen muss. Und ja, ich kompiliere im Release Modus. <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>
]]></description><link>https://www.c-plusplus.net/forum/post/1787541</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787541</guid><dc:creator><![CDATA[marcD22]]></dc:creator><pubDate>Sat, 03 Oct 2009 03:19:30 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 05:08:36 GMT]]></title><description><![CDATA[<p>marcD22 schrieb:</p>
<blockquote>
<p>preoptimal schrieb:</p>
<blockquote>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Abend!</p>
<p>Ich habe in meiner 3D-Anwendung eine Funktion, die sehr oft aufgerufen wird (in jedem Frame einmal)</p>
</blockquote>
<p>Warum? Du must doch deine mVertexMap nur updaten, wenn sich was ändert. Und dann auch nur das was sich ändert. Übrigens Release kompilierst du schon, oder?</p>
</blockquote>
<p>Keine Sorge, ich weiß schon wann ich sie aufrufen muss.</p>
</blockquote>
<p>na dann viel spass</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787542</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787542</guid><dc:creator><![CDATA[preoptimal]]></dc:creator><pubDate>Sat, 03 Oct 2009 05:08:36 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 10:27:35 GMT]]></title><description><![CDATA[<p>marcD22 schrieb:</p>
<blockquote>
<p>Als Zieldatenstruktur hatte ich statt einer std::map einfach einen std::vector&lt;VertexIndexAndHeightPair&gt;. Das hinzufügen (mit push_back) war natürlich sehr schnell, nur war die Suche mittels find(), ob der Index bereits in dem vector ist unglaublich langsam.</p>
</blockquote>
<p>Du könntest vielleicht die Index-Struktur wegschmeissen und stattdessen für den Zugriff einen ganzzahligen Index nehmen: <code>index = zeile * breite + spalte;</code> . Voraussetzung ist, dass du einen Integer-Typen hast, in den Breite * Höhe sicher reinpasst.</p>
<p>Je nach Größe von Breite * Höhe könntest du als weiteren Schritt die Map sparen und mit dem Index einen vector direkt addressieren. Falls du einen vector dieser Größe anlegen kannst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787590</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787590</guid><dc:creator><![CDATA[Registrierter Troll]]></dc:creator><pubDate>Sat, 03 Oct 2009 10:27:35 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 10:36:06 GMT]]></title><description><![CDATA[<p>btw:</p>
<pre><code class="language-cpp">bool operator&lt; (const Index &amp;lhs, const Index &amp;rhs)
{
  if(lhs.row == rhs.row)
    return lhs.col &lt; rhs.col;

  return lhs.row &lt; rhs.row;
}
</code></pre>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787593</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787593</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 03 Oct 2009 10:36:06 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 14:53:11 GMT]]></title><description><![CDATA[<p>Registrierter Troll schrieb:</p>
<blockquote>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Als Zieldatenstruktur hatte ich statt einer std::map einfach einen std::vector&lt;VertexIndexAndHeightPair&gt;. Das hinzufügen (mit push_back) war natürlich sehr schnell, nur war die Suche mittels find(), ob der Index bereits in dem vector ist unglaublich langsam.</p>
</blockquote>
<p>Du könntest vielleicht die Index-Struktur wegschmeissen und stattdessen für den Zugriff einen ganzzahligen Index nehmen: <code>index = zeile * breite + spalte;</code> . Voraussetzung ist, dass du einen Integer-Typen hast, in den Breite * Höhe sicher reinpasst.</p>
<p>Je nach Größe von Breite * Höhe könntest du als weiteren Schritt die Map sparen und mit dem Index einen vector direkt addressieren. Falls du einen vector dieser Größe anlegen kannst.</p>
</blockquote>
<p>Ja, den Gedanken hatte ich auch schon. Wie du richtig erkannt hast, ist mein Index ein Index in einem N x N 2D Gitter, dessen Ausmaße ich kenne. Ich könnte also wie du schon gesagt hast, meinen 2D index umrechnen in einen 1D Index: index = row * breite + column und index als index in einem vector benutzen. Das Problem ist nur: Mein Gitter kann eine Größe bis zu 4000 x 4000 haben und dann hätte ich vektoren mit 16.000.000 Einträgen, obwohl sich die Indices, die ich an addVertices() schicke, sich immer in einem relativ kleinen Block befinden (sprich: es kommt nicht vor, dass ich Indices an addVertices() schicke, die total zerstreut über das ganze Gitter sind. Die Indices liegen alle dicht zusammen in einem bestimmten Bereich (meistens so 30x30 Bereiche) des großen Gitters).<br />
Dieser Ansatz wird also wegen des Speicheraufwandes nicht gehen, oder?</p>
<p>Zu der hash_map: Irgendwie finde ich da recht wenig Anleitungen dazu. Sehe ich das richtig, dass unordered_map und hash_map das selbe ist? Da mein Key ja der struct Index sein wird, muss ich mir ja eine Hashfunktion schreiben, oder?<br />
Was ich bei Hashtabellen nie verstanden habe: Sagen wir meine Hashfunktion sieht so aus:</p>
<pre><code class="language-cpp">int hashFunction(const Index&amp; index) {
   return index.vertexRow * width + index.vertexCol;
}
</code></pre>
<p>Bei einem 4k x 4k Gitter, liefert diese Funktion also Werte im Intervall [0,15999999]. Wieviel Speicher allokiert dann die hashmap? Ich mein, wenn ich jetzt den Index (3999,3999) speichern will, dann liefert die Hashfunktion ja 15999999, dann ist also der Index für diesen Key gleich 15999999, dann muss das Array ja mindestens 16000000 Elemente haben, oder? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787685</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787685</guid><dc:creator><![CDATA[marcD22]]></dc:creator><pubDate>Sat, 03 Oct 2009 14:53:11 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 19:08:11 GMT]]></title><description><![CDATA[<p>marcD22 schrieb:</p>
<blockquote>
<p>Dieser Ansatz wird also wegen des Speicheraufwandes nicht gehen, oder?</p>
</blockquote>
<p>Das kannst nur du wissen. Rechne den Speicherbedarf aus und dann entscheide selbst, ob das geht oder nicht. Aktuelle Rechner haben in der Regel mind. 2 GB Speicher.</p>
<blockquote>
<p>Bei einem 4k x 4k Gitter, liefert diese Funktion also Werte im Intervall [0,15999999]. Wieviel Speicher allokiert dann die hashmap? Ich mein, wenn ich jetzt den Index (3999,3999) speichern will, dann liefert die Hashfunktion ja 15999999, dann ist also der Index für diesen Key gleich 15999999, dann muss das Array ja mindestens 16000000 Elemente haben, oder? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
</blockquote>
<p>Eine Map ist kein Array. Die Map wird näherungsweise so groß wie die Summe der Elemente die drinstecken.</p>
<p>Vielleicht wäre hier ein <a href="http://en.wikipedia.org/wiki/Quadtree" rel="nofollow">QuadTree</a> o. ä. als Datenstruktur besser geeignet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787742</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787742</guid><dc:creator><![CDATA[Registrierter Troll]]></dc:creator><pubDate>Sat, 03 Oct 2009 19:08:11 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sat, 03 Oct 2009 20:43:16 GMT]]></title><description><![CDATA[<p>Registrierter Troll schrieb:</p>
<blockquote>
<blockquote>
<p>Bei einem 4k x 4k Gitter, liefert diese Funktion also Werte im Intervall [0,15999999]. Wieviel Speicher allokiert dann die hashmap? Ich mein, wenn ich jetzt den Index (3999,3999) speichern will, dann liefert die Hashfunktion ja 15999999, dann ist also der Index für diesen Key gleich 15999999, dann muss das Array ja mindestens 16000000 Elemente haben, oder? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
</blockquote>
<p>Eine Map ist kein Array. Die Map wird näherungsweise so groß wie die Summe der Elemente die drinstecken.</p>
</blockquote>
<p>Hm, wie gesagt, ich versteh nicht wirklich WIE eine Hashmap intern nun speichert. Ich glaube mal gelesen zu haben, dass sie ein Array benutzt.<br />
Das läuft doch so: Wenn ich einer hashmap m ein Key/Value Pärchen hinzufüge:<br />
m.insert( value_type(key, value) )<br />
dann berechnet die hashmap den hash per: int hash = hashFunction(key). Ich dachte, dass eine hashmap jetzt ein Array hat, wobei jedes Element ein Zeiger auf irgend eine Datenstrukur ist (sagen wir mal vector), weil es ja zu Kollisionen kommen kann. Ich dachte also, die speicherung sieht in etwa so aus:<br />
std::vector&lt;Value_Type&gt;* data[???];<br />
data[hash]-&gt;push_back(value);<br />
Aber offenbar wird das ja nicht so gemacht, oder? Weil sonst bräuchte ja meine hashmap ein array mit 16000000 Einträgen, da ja hashFunction( (3999,3999) ) den hash 15999999 liefert und die map jetzt data[15999999]-&gt;push_back(...) machen müsste.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787763</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787763</guid><dc:creator><![CDATA[marcD22]]></dc:creator><pubDate>Sat, 03 Oct 2009 20:43:16 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sun, 04 Oct 2009 00:17:29 GMT]]></title><description><![CDATA[<p><a href="http://de.wikipedia.org/wiki/Hashtabelle" rel="nofollow">http://de.wikipedia.org/wiki/Hashtabelle</a><br />
sollte eigtl deine - mir nicht ganz ersichtliche - Frage beantworten...</p>
<p>Vll meinst du das<br />
<a href="http://de.wikipedia.org/wiki/Hashtabelle#Dynamisches_Hashing" rel="nofollow">http://de.wikipedia.org/wiki/Hashtabelle#Dynamisches_Hashing</a></p>
<p>ansonsten könntest du auch noch meinen, wie das ganze intern gespeichert wird...<br />
da eine hashmap im best-case eine zugriffszeit von O(1) hat, wird ein Array der (maximal-)Länge hashfkt_max wohl unabdingbar sein...<br />
Allerdings kann das mittels Pointern ja relativ klein gehalten werden...</p>
<pre><code class="language-cpp">template &lt;
  typename key_type,
  typename mapped_type
//...
&gt;
class map
{
  std::vector&lt; mapped_type* &gt; hash_map;

  size_type hash_fkt(const key_type &amp;key)
  {
    return /*wie auch immer so ne fkt aussehen könnte*/ size_type(key);
  }

  map()
  {}

  iterator real_insert(const std::pair&lt;key_type, mapped_type&gt; &amp;to_add)
  {
    std::size_t index = hash_fkt(to_add.first());

    hash_map.reserve(index+1);
    while(index &gt;= hash_map.size())
      hash_map.push_back(nullptr);

    if(! hash_map[index])
      hash_map[index] = new mapped_type(to_add.second());
    else
      //kollisionserkennung - siehe wikipedia

    return iterator(&amp;hash_map[index]);
  }
};
</code></pre>
<p>so würde man auf 32bit Systemen mit einer Hash-Fkt die keine Kollisionen erzeugt max. 16'000'000*4 / 2^20 MB Speicher am Stück brauchen (ein wenig mehr als 60MB) - unabhängig von mapped_type.<br />
Außerdem bräuchte man nich mal ein swap für mapped_type.</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787804</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787804</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sun, 04 Oct 2009 00:17:29 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sun, 04 Oct 2009 00:32:58 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/16305">@unskilled</a>: Das mir an einer Hashtabelle nie so ganz klar, sieht man auch in deinem Code. Nämlich die Zeile 22: hash_map.reserve(index+1); Das Problem ist ja, dass die Klasse Map nicht wissen, was der Maximalwert meiner Hash Funktion ist (in meinem Fall 15999999).<br />
Dh im schlimmsten Fall ist jeder eingefügte Key größer als der davor und du würdest in deinem Code ständig reserve() machen, mit all den Problemen die dazu gehören (Werte umkopieren etc).</p>
<p>Was ich nicht verstehe: Ich habe jetzt eine Hashmap genommen und habe folgende Hashfunktion:</p>
<pre><code class="language-cpp">int hashFunction(const Index&amp; index) {
   return index.vertexRow * width + index.vertexCol;
}
</code></pre>
<p>Width ist bei mir 1025 (ich habe ein 1025 x 1025 Gitter). Das bedeutet also, dass meine Funktion injektiv ist. Index (2,3) wird auf 2053 abgebildet und KEIN anderer Index kann auf 2053 abgebildet werden. Da müsste dann doch sowohl find() also auch insert() in die Map O(1) sein? Ist es aber offenbar nicht, denn der Code ist nach wie vor langsam. Wenn ich den insert:<br />
mHashMap.insert( HashMap::value_type(i, h) ); auskommentiere, dann ist der Code wieder schnell.<br />
Wie kann das insert() so lahm sein, wenn ich doch eine Hashfunktion habe, die niemals Kollisionen erzeugt? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787806</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787806</guid><dc:creator><![CDATA[marcD22]]></dc:creator><pubDate>Sun, 04 Oct 2009 00:32:58 GMT</pubDate></item><item><title><![CDATA[Reply to Funktion schneller machen on Sun, 04 Oct 2009 01:32:01 GMT]]></title><description><![CDATA[<p>marcD22 schrieb:</p>
<blockquote>
<p>Das Problem ist ja, dass die Klasse Map nicht wissen, was der Maximalwert meiner Hash Funktion ist (in meinem Fall 15999999).</p>
</blockquote>
<p>Wozu muss sie sowas denn bitte wissen? Das braucht man doch nirgendwo...</p>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Nämlich die Zeile 22: hash_map.reserve(index+1);<br />
Dh im schlimmsten Fall ist jeder eingefügte Key größer als der davor und du würdest in deinem Code ständig reserve() machen, mit all den Problemen die dazu gehören (Werte umkopieren etc).</p>
</blockquote>
<p>Das ist richtig - schlimmstenfalls wird also aller &lt;vernachlässigbar&gt; aufrufe &lt;vernachlässigbar&gt; viel kopiert...<br />
gehen wir mal von 1'000'000 Zeigern aus - bei einer Verdoppelung des Vector-Speicherplatzes (wovon immer gern ausgegangen wird) haben wir hier die nächste Umkopier-aktion, nachdem wir 1'000'000 Zeiger hinzugefügt(aber keine entfernt) haben. Wir würden dann 1*10^6*4 / 1024 KB kopieren:<br />
ca. 3900KB = &lt;4MB<br />
Jz kannst du mal gucken, wie schnell der Durchschnitts-RAM lesen und schreiben kann... Hab leider auf die Schnelle keine Werte gefunden - sollte aber im Gbps-Bereich liegen...<br />
also:<br />
aller n zusätzlicher werte wird ein von n abhängiger kleiner speicherblock kopiert...<br />
das macht map auch zum nicht-optimalen container bei verhältnismäßig vielen einfüge-operationen und wenig find`s...</p>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Was ich nicht verstehe: Ich habe jetzt eine Hashmap genommen und habe folgende Hashfunktion:</p>
<pre><code class="language-cpp">int hashFunction(const Index&amp; index) {
   return index.vertexRow * width + index.vertexCol;
}
</code></pre>
<p>Width ist bei mir 1025 (ich habe ein 1025 x 1025 Gitter). Das bedeutet also, dass meine Funktion injektiv ist. Index (2,3) wird auf 2053 abgebildet und KEIN anderer Index kann auf 2053 abgebildet werden. Da müsste dann doch sowohl find() also auch insert() in die Map O(1) sein?</p>
</blockquote>
<p>find() auf jeden fall<br />
insert() hat wie oben beschrieben im worst-case eine laufzeit von O(n), aber du kannst im Durchschnitt mit O(1) rechnen...</p>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Ist es aber offenbar nicht, denn der Code ist nach wie vor langsam. Wenn ich den insert:<br />
mHashMap.insert( HashMap::value_type(i, h) ); auskommentiere, dann ist der Code wieder schnell.</p>
</blockquote>
<p>Ich weiß, du hattest schon mal gesagt, dass du den release-Modus nutzt - immernoch?</p>
<p>marcD22 schrieb:</p>
<blockquote>
<p>Wie kann das insert() so lahm sein, wenn ich doch eine Hashfunktion habe, die niemals Kollisionen erzeugt? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
</blockquote>
<p>1. woher soll der statische code das wissen?<br />
2. siehe oben... <a href="http://images.google.de/images?hl=de&amp;source=hp&amp;q=container%20choice&amp;um=1&amp;ie=UTF-8&amp;sa=N&amp;tab=wi" rel="nofollow">http://images.google.de/images?hl=de&amp;source=hp&amp;q=container choice&amp;um=1&amp;ie=UTF-8&amp;sa=N&amp;tab=wi</a></p>
<p>Evtl ist hier eine eigene Datenstruktur keine dumme Idee...<br />
So, wie es sich anhört reicht ja:</p>
<pre><code class="language-cpp">struct 2d_arr
{
private:
  size_type x;
  std::vector&lt;T&gt; data;

public:
  2d_arr(size_type x, size_type y)
  : x(x),
    data(x*y)
  {}

  const T&amp; operator() (size_type i, size_type j) const
  {
    const_iterator it = data.begin();
    std::advance(it, i+j*x);
    return *it;
  }

  T&amp; operator() (size_type i, size_type j)
  {
    iterator it = data.begin();
    std::advance(it, i+j*x);
    return *it;
  } 
};
</code></pre>
<p>hat ne garantiert konstante Laufzeit - bei einfüge und lese-operationen...</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1787809</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1787809</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sun, 04 Oct 2009 01:32:01 GMT</pubDate></item></channel></rss>