<?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[Batcher odd–even mergesort metaprogramm]]></title><description><![CDATA[<p>ist es möglich sich den code für &quot;<a href="https://en.wikipedia.org/wiki/Batcher_odd%E2%80%93even_mergesort" rel="nofollow">Batcher odd–even mergesort</a>&quot; von templates generieren zu lassen? so dass man am ende nur noch &quot;sort&lt;5&gt;&quot; schreiben muss und im hintergrund die korrekten swap-instruktionen im funktionstemplate landen. ich hab leider nur die direkte laufzeit-lösung geschafft.</p>
<p>hab mir auch gedacht dass man da was mit makros anstellen könnte aber das ist nichts geworden da dafür schon bisschen komplexere logik von nöten ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/326840/batcher-odd-even-mergesort-metaprogramm</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Jul 2026 20:23:35 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/326840.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 09 Jul 2014 19:14:32 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 19:14:32 GMT]]></title><description><![CDATA[<p>ist es möglich sich den code für &quot;<a href="https://en.wikipedia.org/wiki/Batcher_odd%E2%80%93even_mergesort" rel="nofollow">Batcher odd–even mergesort</a>&quot; von templates generieren zu lassen? so dass man am ende nur noch &quot;sort&lt;5&gt;&quot; schreiben muss und im hintergrund die korrekten swap-instruktionen im funktionstemplate landen. ich hab leider nur die direkte laufzeit-lösung geschafft.</p>
<p>hab mir auch gedacht dass man da was mit makros anstellen könnte aber das ist nichts geworden da dafür schon bisschen komplexere logik von nöten ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2407844</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407844</guid><dc:creator><![CDATA[GTCML]]></dc:creator><pubDate>Wed, 09 Jul 2014 19:14:32 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 20:40:37 GMT]]></title><description><![CDATA[<p>Eben schnell<sup>*</sup> runtergetippt, bestimmt noch verbesserungswürdig:</p>
<pre><code>#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;

template &lt;std::size_t N, std::size_t step_size, std::size_t step = 1&gt; struct odd_even_compare
{
  template&lt;typename Iterator&gt; void operator() (Iterator it)
  {
    if (it[step * step_size + step_size] &lt; it[step * step_size])
      std::swap(it[step * step_size + step_size], it[step * step_size]);
    odd_even_compare&lt;N, step_size, step + 1&gt;()(it);
  }
};

template&lt;&gt; template &lt;std::size_t N, std::size_t step_size&gt; struct odd_even_compare&lt;N, step_size, N&gt;
{
  template&lt;typename Iterator&gt; void operator() (Iterator it)
  {
    if (it[N * step_size + step_size] &lt; it[N * step_size])
      std::swap(it[N * step_size + step_size], it[N * step_size]);
  }
};

template &lt;std::size_t N, std::size_t step_size = 1&gt; struct odd_even_merge
{
  template&lt;typename Iterator&gt; void operator()(Iterator it)
  {
    odd_even_merge&lt;N/2, 2 * step_size&gt;()(it);
    odd_even_merge&lt;N/2, 2 * step_size&gt;()(it + step_size);
    odd_even_compare&lt;N - 3, step_size&gt;()(it);
  }
};

template&lt;&gt; template&lt;std::size_t step_size&gt; struct odd_even_merge&lt;2, step_size&gt;
{
  template&lt;typename Iterator&gt; void operator()(Iterator it)
  {
    if (it[step_size] &lt; it[0])
      std::swap(it[0], it[step_size]);
  }
};

template &lt;std::size_t N&gt; struct odd_even_mergesort
{
  template&lt;typename Iterator&gt; void operator()(Iterator it)
  {
    odd_even_mergesort&lt;N/2&gt;()(it);
    odd_even_mergesort&lt;N/2&gt;()(it + N/2);
    odd_even_merge&lt;N&gt;()(it);
  }
};

template&lt;&gt; struct odd_even_mergesort&lt;1&gt;
{template&lt;typename Iterator&gt; void operator() (Iterator) {}};

template&lt;&gt; struct odd_even_mergesort&lt;0&gt;
{template&lt;typename Iterator&gt; void operator() (Iterator) {}};

int main()
{
  std::vector&lt;int&gt; foo = {2,6,3,8,3,3,7,9};
  odd_even_mergesort&lt;8&gt;()(foo.begin());
  for (auto it : foo)
    std::cout &lt;&lt; it &lt;&lt; '\n';
}
</code></pre>
<p>Ob das jetzt wirklich wie gewünscht instanziert wird, kann ich aufgrund meiner bescheidenen Assemblerkenntnisse nicht mit absoluter Sicherheit sagen. Es kommen im Maschinencode (GCC 4.8) jedenfalls sehr oft sich wiederholende Abschnitte der folgenden Form vor:</p>
<pre><code>movl	12(%r12), %edx
	cmpl	%eax, %edx
	jge	.L14
	movl	%edx, 8(%r12)
	movl	%eax, 12(%r12)
	movl	%eax, %edx
</code></pre>
<p>Mit jeweils leicht anderen Zahlen, die jeweils irgendwie nach den Zahlenpaaren aussehen, die man erwarten würde. Und wenn ich das richtig interpretiere, ist das ein if mit anschließendem swap, das wir hier sehen. Also Erfolg <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><sup>*</sup>: &quot;schnell&quot; ist natürlich relativ zu sehen. Es ist immer noch Templatebrainfuck. Dafür habe ich immerhin ~30 Minuten gebraucht, obwohl ich mir nicht viel Mühe gegeben habe. Sofortige Verbesserungen wären natürlich eine variable Vergleichsfunktion, sowie eine Prüfung, ob N überhaupt eine Zweierpotenz ist. Und die anfängliche Prüfung, ob N &gt;= 2 ist geht bestimmt auch etwas eleganter. Die naheliegende Methode, noch einen bool ( N &gt; 1) als weiteren Templateparameter zu nutzen führt eher zu mehr Obfuscation anstatt zu Übersicht.<br />
P.S.: Und das mit dem <code>step_size</code> ist natürlich auch so ein Hack. Ich hatte mir irgendwie vorgestellt, da einen &quot;View&quot; auf die Unterliste zu erstellen. Aber das würde wohl vermutlich mindestens einen Wrapper um den Iterator nötig machen. Entgegen anderslautender Gerüchte habe ich aber nicht den ganzen Tag Zeit <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2407860</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407860</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Wed, 09 Jul 2014 20:40:37 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 20:51:00 GMT]]></title><description><![CDATA[<p>oha, gleich so!<br />
danke dir vielmals für die arbeit, ich versuche es nachzuvollziehen so gut wie möglich, sieht jedoch nicht leicht aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2407867</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407867</guid><dc:creator><![CDATA[GTCML]]></dc:creator><pubDate>Wed, 09 Jul 2014 20:51:00 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 21:04:07 GMT]]></title><description><![CDATA[<p>GTCML schrieb:</p>
<blockquote>
<p>oha, gleich so!<br />
danke dir vielmals für die arbeit, ich versuche es nachzuvollziehen so gut wie möglich, sieht jedoch nicht leicht aus.</p>
</blockquote>
<p>Nanu? Ich hatte nach deiner Frage eigentlich erwartet, dass du mit TMP vertraut bist. Obiger Code ist doch relativ harmlos in dieser Hinsicht. Kleines TMP-Einmaleins gefällig?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2407869</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407869</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Wed, 09 Jul 2014 21:04:07 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 21:11:32 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>GTCML schrieb:</p>
<blockquote>
<p>oha, gleich so!<br />
danke dir vielmals für die arbeit, ich versuche es nachzuvollziehen so gut wie möglich, sieht jedoch nicht leicht aus.</p>
</blockquote>
<p>Nanu? Ich hatte nach deiner Frage eigentlich erwartet, dass du mit TMP vertraut bist. Obiger Code ist doch relativ harmlos in dieser Hinsicht. Kleines TMP-Einmaleins gefällig?</p>
</blockquote>
<p>oh nein, das kann ich jetzt wirklich nicht auch noch annehmen. tmp ist mir bekannt und ich dürfte es auch nachvollziehen können, benötige jedoch ein bisschen zeit da es mir leider nicht so geläufig ist. wie oft macht mach denn schon was mit tmp... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2407874</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407874</guid><dc:creator><![CDATA[GTCML]]></dc:creator><pubDate>Wed, 09 Jul 2014 21:11:32 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 21:24:24 GMT]]></title><description><![CDATA[<p>GTCML schrieb:</p>
<blockquote>
<p>wie oft macht mach denn schon was mit tmp... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Praktisch so gut wie nie, aber du hast ja (anscheinend ungewollt) direkt nach einer solchen Lösung gefragt. Die einzige Möglichkeit, auf der Templateebene Programme zu erstellen ist schließlich logischerweise Templatemetaprogrammierung.</p>
<p>Dann mal viel Spaß beim Enttüfteln. Ich schätze, wenn du TMP nie gesehen hast, ist das ein echt harter Brocken, auch wenn's für den Experten ein recht einfaches Programm ist. Guck dir vielleicht zuerst einmal eine einfache Fakultätsfunktion in einer Einführung für TMP an. Das was du hier siehst ist dann nicht viel komplexer, bloß dieses Grundprinzip 3x verschachtelt (und mit structs statt Funktionen, weil man Funktionen nicht partiell spezialisieren kann).<br />
Aber mindestens diese Grundprinzipien der TMP musst du mal an einfachen Beispielen gesehen haben, sonst blickt man bei solchen Code nicht durch. Templatespezialisierung und Rekursion hat man ja vielleicht mal gehört, aber das ist sind ja auch so Sprachmittel, die man praktisch sonst fast nie braucht und daher den Anblick nicht gewohnt ist. Es sollte aber leicht sein, Einführungen im Netz zu finden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2407877</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407877</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Wed, 09 Jul 2014 21:24:24 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 22:08:21 GMT]]></title><description><![CDATA[<p>Andere Variante, den Beispielcode einigermaßen 1:1 nachgemacht</p>
<pre><code class="language-cpp">#include &lt;vector&gt;
#include &lt;iostream&gt;

template &lt;typename T&gt;
using eval = typename T::type;

template &lt;typename T&gt; struct identity
{
   using type = T;
};

template &lt;int... i&gt; struct index_list : identity&lt;index_list&lt;i...&gt;&gt; {};

template &lt;int N, int... i&gt; struct make_index_list : make_index_list&lt;N-1, 0, 1+i...&gt; {};

template &lt;int... i&gt; struct make_index_list&lt;0, i...&gt; : index_list&lt;i...&gt; {};

template &lt;typename... T&gt; struct type_list : identity&lt;type_list&lt;T...&gt;&gt; {};

template &lt;typename... T&gt; struct merge_type_lists : merge_type_lists&lt;eval&lt;T&gt;...&gt; {};
template &lt;typename... T, typename... U, typename... V&gt;
struct merge_type_lists&lt;type_list&lt;T...&gt;, type_list&lt;U...&gt;, V...&gt;
    : merge_type_lists&lt;type_list&lt;T..., U...&gt;, V...&gt;
{};
template &lt;typename... T&gt;
struct merge_type_lists&lt;type_list&lt;T...&gt;&gt;
    : type_list&lt;T...&gt;
{};

/////////////////////////////////////
template &lt;int a, int b&gt;
struct index_pair
{
    static constexpr auto first = a;
    static constexpr auto second = b;
};

template &lt;int lo, int hi, int r, typename = eval&lt;make_index_list&lt;(hi-lo)/(2*r)&gt;&gt;&gt;
struct oddeven_merge_simple_range;
template &lt;int lo, int hi, int r, int... I&gt;
struct oddeven_merge_simple_range&lt;lo, hi, r, index_list&lt;I...&gt;&gt;
    : type_list&lt;index_pair&lt;lo+r+I*2*r,lo+2*r+I*2*r&gt;...&gt;
{};

template &lt;int lo, int hi, int r&gt;
struct oddeven_merge
    : std::conditional&lt;(r*2&lt;hi-lo),
                       merge_type_lists&lt;oddeven_merge&lt;lo, hi, 2*r&gt;, oddeven_merge&lt;lo+r, hi, 2*r&gt;, oddeven_merge_simple_range&lt;lo, hi, r&gt;&gt;,
                       type_list&lt;index_pair&lt;lo, lo+r&gt;&gt;&gt;::type
{};

template &lt;int lo, int hi&gt;
struct oddeven_merge_sort_range
    : std::conditional&lt;(lo&lt;hi),
                       merge_type_lists&lt;oddeven_merge_sort_range&lt;lo, lo+(hi-lo)/2&gt;, oddeven_merge_sort_range&lt;lo+(hi-lo)/2+1,hi&gt;, oddeven_merge&lt;lo,hi,1&gt;&gt;,
                       type_list&lt;&gt;&gt;::type
{};

template &lt;typename RandomIter, typename... Pairs&gt;
void oddeven_merge_sort(RandomIter begin, type_list&lt;Pairs...&gt;)
{
    bool show[] = { std::cout &lt;&lt; '(' &lt;&lt; Pairs::first &lt;&lt; ',' &lt;&lt; Pairs::second &lt;&lt; &quot;), &quot;... };
    std::cout &lt;&lt; '\n';
    bool sort[] = { ((begin[Pairs::second]&lt;begin[Pairs::first]?std::swap(begin[Pairs::second],begin[Pairs::first]):void()),false)... };
}

template &lt;std::size_t N, typename RandomIter&gt;
void oddeven_merge_sort(RandomIter begin)
{
    static_assert( N&gt;0 &amp;&amp; (N&amp;(N-1))==0, &quot;N must be power of 2&quot; );
    oddeven_merge_sort(begin, eval&lt;oddeven_merge_sort_range&lt;0, N-1&gt;&gt;{});
}

int main()
{
    std::vector&lt;int&gt; v = { 2, 4, 3, 5, 6, 1, 7, 8 };
    oddeven_merge_sort&lt;8&gt;(v.begin());
    for ( auto i : v )
        std::cout &lt;&lt; i &lt;&lt; '\t';
    std::cout &lt;&lt; '\n';
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2407885</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407885</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Wed, 09 Jul 2014 22:08:21 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Wed, 09 Jul 2014 23:04:36 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Andere Variante, den Beispielcode einigermaßen 1:1 nachgemacht</p>
</blockquote>
<p>Das sollte ich vielleicht noch erwähnen: Ich habe den Code (d.h. die abstrakte Formulierung oben auf der Seite, nicht den Beispielcode weiter unten) von<br />
<a href="http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/networks/oemen.htm" rel="nofollow">http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/networks/oemen.htm</a><br />
nachgemacht. Damit ist für den TE wohl leichter zu verstehen, wie man darauf kommt, da man fast alles ganz direkt übernehmen kann. Bloß die Schleife &quot;compare [ai : ai+1] for all i element {1, 3, 5, 7, ..., n-3}&quot; muss man rekursiv umschreiben.</p>
<p>P.S.: Ich sehe gerade, der Beispielcode auf der verlinkten Seite entspricht auch fast 1:1 meinem Programm, aber eben zur Laufzeit. Es wird sogar auch der Weg über eine step_size gewählt. Ich hatte den Beispielcode unten gar nicht gesehen, da ich die Seite einfach von oben nach unten gelesen und nachprogrammiert habe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2407893</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2407893</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Wed, 09 Jul 2014 23:04:36 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Tue, 22 Jul 2014 08:35:27 GMT]]></title><description><![CDATA[<p>Ich hab mich auch rangesetzt</p>
<pre><code>template &lt;typename I&gt;
	void compare_swap( I a, I b )
	{
		if (*a &gt; *b)
			std::iter_swap(a, b);
	}

	template &lt;std::size_t lo, std::size_t hi, std::size_t r&gt;
	struct oddeven_merge
	{
		template &lt;typename Iter&gt;
		void operator()(Iter first)
		{
			call_(first, std::integral_constant&lt;bool, step &lt; hi - lo&gt;{});
		}

	private:
		static auto const step = 2*r;

		template &lt;typename Iter&gt;
		static void call_(Iter first, std::true_type)
		{
			oddeven_merge&lt;lo    , hi, step&gt;{}(first);
			oddeven_merge&lt;lo + r, hi, step&gt;{}(first);

			for (std::size_t i = lo + r; i &lt;= hi - r; i += step)
				compare_swap(first + i, first + i + r);
		}

		template &lt;typename Iter&gt;
		static void call_(Iter first, std::false_type)
		{
			compare_swap(first + lo, first + lo + r);
		}
	};

	template &lt;std::size_t lo, std::size_t hi&gt;
	struct oddeven_merge_sort_range
	{
		static auto const mid = lo + (hi-lo)/2;

		template &lt;typename Iter&gt;
		void operator()( Iter first )
		{
			oddeven_merge_sort_range&lt;lo   , mid&gt;{}(first);
			oddeven_merge_sort_range&lt;mid+1, hi &gt;{}(first);
			oddeven_merge&lt;lo, hi, 1&gt;{}(first);
		}
	};

	template &lt;std::size_t lo&gt;
	struct oddeven_merge_sort_range&lt;lo, lo&gt;
	{
		template &lt;typename I&gt; void operator()(I) {}
	};

	template &lt;std::size_t N, typename Iter&gt;
	void oddeven_merge_sort( Iter i )
	{
		static_assert( (N &amp; (N-1)) == 0 &amp;&amp; N != 0, &quot;N must be a power of 2&quot; );
		oddeven_merge_sort_range&lt;0, N-1&gt;{}(i);
	}
</code></pre>
<p>Hmm.</p>
<pre><code>#include &lt;algorithm&gt;   // iter_swap
#include &lt;type_traits&gt; // integral_constant / false_type / true_type
#include &lt;iostream&gt;
#include &lt;array&gt;

namespace Arcoth
{
    // […]
}

namespace camper
{

    // […]

	struct evaluator
	{
		template &lt;typename... Args&gt;
		evaluator(Args&amp;&amp;...) {}
	};
	void evaluate(evaluator) {}

	template &lt;typename RandomIter, typename... Pairs&gt;
	void oddeven_merge_sort(RandomIter begin, type_list&lt;Pairs...&gt;)
	{
		evaluate({ ((begin[Pairs::second]&lt;begin[Pairs::first]?std::swap(begin[Pairs::second],begin[Pairs::first]):void()),false)... });
	}

    // […]
}

namespace SeppJ
{
    // […]
}

#include &lt;random&gt;
#include &lt;memory&gt;

template &lt;std::size_t N,
          std::size_t outer_loopings,
          std::size_t inner_loopings,
          typename T&gt;
void test(T obj, int64_t const* values)
{
	auto best = std::numeric_limits&lt;clock_t&gt;::max();

	uint64_t check;

	uint64_t array[N*inner_loopings];

	for (unsigned j = 0; j != outer_loopings; ++j )
	{
		check = 0;

		std::copy_n( values, N*inner_loopings, array );

		auto start = clock();

			for (unsigned i = 0; i != inner_loopings; ++i)
			{
				obj( array + N*i );

				for (std::size_t c = 0; c != N; c += 2)
					(check += array[c]) *= array[c+1];
			}

		auto time = clock() - start;

		if (time &lt; best)
		{
			best = time;
			j = 0;
		}
	}

	std::cout &lt;&lt; 1. * best / CLOCKS_PER_SEC &lt;&lt; ' ' &lt;&lt; std::hex &lt;&lt; check &lt;&lt; '\n';
}

int main()
{
	auto constexpr size = 256, inner = 512, outer = 5000;

	std::uniform_int_distribution&lt;int64_t&gt; dis(std::numeric_limits&lt;int64_t&gt;::min());
	std::mt19937_64 engine( std::random_device{}() );

	int64_t values[size*inner];

	std::generate( std::begin(values), std::end(values), [&amp;] {return dis(engine);} );

	std::cout &lt;&lt; &quot;SeppJ : &quot;; test&lt;size, outer, inner&gt;( SeppJ::odd_even_mergesort&lt;size&gt;{}                       , values );
	std::cout &lt;&lt; &quot;camper: &quot;; test&lt;size, outer, inner&gt;( [] (auto iter) {camper::oddeven_merge_sort&lt;size&gt;(iter);}, values );
	std::cout &lt;&lt; &quot;Arcoth: &quot;; test&lt;size, outer, inner&gt;( [] (auto iter) {Arcoth::oddeven_merge_sort&lt;size&gt;(iter);}, values );
}
</code></pre>
<pre><code>clang++ -O3 -Wall -std=c++1y -mtune=native -march=native -funroll-loops ....
SeppJ : 0.006129 def6daed3282e743
camper: 0.010375 def6daed3282e743
Arcoth: 0.007321 def6daed3282e743
</code></pre>
<p>Merkwürdig. Warum ist SeppJs Variante so viel schneller?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2409897</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2409897</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Tue, 22 Jul 2014 08:35:27 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Tue, 22 Jul 2014 09:13:35 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>Merkwürdig. Warum ist SeppJs Variante so viel schneller?</p>
</blockquote>
<p>Theoretisch müssten die Varianten ja eigentlich alle gleich schnell sein, weil sie alle zu einer Serie von Compare-and-swap degenerien. Evtl. wird eine Variante nicht so stark geinled?<br />
Poste mal bitte auf ideone, damit ich den Code nicht selbst zusammensetzen muss.<br />
Wäre auch interessant, ob evtl. ein einfacher Loop besser abschneidet - bei Sortiergrösse 256 dürfte der compilierte COde recht groß werden, was dann ggf. zu Problemen mit dem Cache führt.<br />
z.B. meine Variante ändern zu</p>
<pre><code class="language-cpp">template &lt;typename RandomIter, typename... Pairs&gt;
    void oddeven_merge_sort(RandomIter begin, type_list&lt;Pairs...&gt;)
    {
        static constexpr auto pairs[][2] = { { Pairs::first, Pairs::second }... };
        for ( int i = 0; i != sizeof...(Pairs); ++i )
            if (begin[pairs[i][1&rsqb;&rsqb;&lt;begin[pairs[i][0&rsqb;&rsqb;)
                std::swap(begin[pairs[i][1&rsqb;&rsqb;,begin[pairs[i][0&rsqb;&rsqb;));
    }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2409909</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2409909</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 22 Jul 2014 09:13:35 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Tue, 22 Jul 2014 09:27:42 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Arcoth schrieb:</p>
<blockquote>
<p>Merkwürdig. Warum ist SeppJs Variante so viel schneller?</p>
</blockquote>
<p>Theoretisch müssten die Varianten ja eigentlich alle gleich schnell sein, weil sie alle zu einer Serie von Compare-and-swap degenerien. Evtl. wird eine Variante nicht so stark geinled?<br />
Poste mal bitte auf ideone, damit ich den Code nicht selbst zusammensetzen muss.<br />
Wäre auch interessant, ob evtl. ein einfacher Loop besser abschneidet - bei Sortiergrösse 256 dürfte der compilierte COde recht groß werden, was dann ggf. zu Problemen mit dem Cache führt.<br />
z.B. meine Variante ändern zu</p>
<pre><code class="language-cpp">template &lt;typename RandomIter, typename... Pairs&gt;
    void oddeven_merge_sort(RandomIter begin, type_list&lt;Pairs...&gt;)
    {
        static constexpr auto pairs[][2] = { { Pairs::first, Pairs::second }... };
        for ( int i = 0; i != sizeof...(Pairs); ++i )
            if (begin[pairs[i][1&rsqb;&rsqb;&lt;begin[pairs[i][0&rsqb;&rsqb;)
                std::swap(begin[pairs[i][1&rsqb;&rsqb;,begin[pairs[i][0&rsqb;&rsqb;));
    }
</code></pre>
</blockquote>
<p>P.S. -march=x impliziert -mtune=x</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2409910</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2409910</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 22 Jul 2014 09:27:42 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Tue, 22 Jul 2014 09:38:23 GMT]]></title><description><![CDATA[<blockquote>
<p>Poste mal bitte auf ideone, damit ich den Code nicht selbst zusammensetzen muss.</p>
</blockquote>
<p>Ideone ist von gestern. <a href="http://coliru.stacked-crooked.com/a/a5ae97d2628fba62" rel="nofollow">http://coliru.stacked-crooked.com/a/a5ae97d2628fba62</a></p>
<blockquote>
<p>z.B. meine Variante ändern zu […]</p>
</blockquote>
<p>Es gibt keine Arrays mit placeholder-Typen.</p>
<p>Ich musste dein Ding abändern zu</p>
<pre><code>static constexpr std::size_t pairs[][2] = { { Pairs::first, Pairs::second }... };
		for ( int i = 0; i != sizeof...(Pairs); ++i )
			Arcoth::compare_swap( begin[pairs[i][0&rsqb;&rsqb;, begin[pairs[i][1&rsqb;&rsqb; ); // der kürze wegen
</code></pre>
<p>(Wollte zuerst <code>common_type_t</code> benutzen, hat aber die rekursive Instantiierungstiefe gesprengt :D)</p>
<p>Die Werte habe ich abgeändert;</p>
<pre><code>auto constexpr size = 64, inner = 2048, outer = 5000;
</code></pre>
<p>Jetzt bekomme ich</p>
<pre><code>SeppJ : 0.00344 133a82bb543c6e04
camper: 0.004839 133a82bb543c6e04
Arcoth: 0.003673 133a82bb543c6e04
</code></pre>
<blockquote>
<p>P.S. -march=x impliziert -mtune=x</p>
</blockquote>
<p>Danke, wusst' ich nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2409913</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2409913</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Tue, 22 Jul 2014 09:38:23 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Tue, 22 Jul 2014 09:36:01 GMT]]></title><description><![CDATA[<p>Behalte ich die alten Werte bei bekomme ich mit deiner neuen Variante nichts neues</p>
<pre><code>SeppJ : 0.005957 f1b8f530f52e022a
camper: 0.007964 f1b8f530f52e022a
Arcoth: 0.006955 f1b8f530f52e022a
</code></pre>
<p>Übrigens, eine lustige compare-swap Implementierung:</p>
<pre><code>std::tie(a, b) = std::minmax(a, b);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2409914</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2409914</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Tue, 22 Jul 2014 09:36:01 GMT</pubDate></item><item><title><![CDATA[Reply to Batcher odd–even mergesort metaprogramm on Tue, 22 Jul 2014 10:22:36 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>(Wollte zuerst <code>common_type_t</code> benutzen, hat aber die rekursive Instantiierungstiefe gesprengt :D)</p>
</blockquote>
<p>clang ist da traditionell etwas beschränkt, mit -ftemplate-depth aber in diesem Fall in den Griff zu kriegen.</p>
<p>Zweckmäßiger wäre hier allerdings ein Typ, der gerade groß genug ist. Kein Grund Platz in der LUT zu verschwenden. unsigned char reicht ja.</p>
<p>Mit einer kleinen Änderung der Messmethode (sonst kommt bei mir nur 0 raus) erhalte ich (<a href="http://ideone.com/B3LCuj" rel="nofollow">http://ideone.com/B3LCuj</a>)</p>
<p>g++ 4.9.0 schrieb:</p>
<blockquote>
<p>SeppJ: 4791639 66b2c7389fd2fd4a<br />
camper(Loop): 5632998 66b2c7389fd2fd4a<br />
camper(unrolled): 4816390 66b2c7389fd2fd4a<br />
Arcoth: 4774074 66b2c7389fd2fd4a</p>
</blockquote>
<p>also kéine nenneswerten Unterscheide (1% ist nicht signifikant)</p>
<p>clang++ 3.4.2 schrieb:</p>
<blockquote>
<p>SeppJ: 4339676 c72e03ba154529b6<br />
camper(Loop): 6114103 c72e03ba154529b6<br />
camper(unrolled): 4416267 c72e03ba154529b6<br />
Arcoth: 4580412 c72e03ba154529b6</p>
</blockquote>
<p>Hier spielen die Eigenarten des Compilers offenbar eine große Rolle (Zeiten zwischen den Compilern sind nicht vergleichbar).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2409918</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2409918</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 22 Jul 2014 10:22:36 GMT</pubDate></item></channel></rss>