<?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[Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance?]]></title><description><![CDATA[<p>Hallo</p>
<p>Am besten erkläre ich es an einem Beispiel, das zählt, wie oft ein Wert in einem Array vorkommt (mein performancekritisches Problem ist analog dazu)</p>
<pre><code>int func1(int* array, int number, int value){
  int number_of_value = 0;
  for(int i=0; i&lt;number; i++){
    if(array[i] == value)
      number_of_value++;
  }
  return number_of_value;
}

int func2(int* array, int number, int value){
  int number_of_value = 0;
  for(int i = number-1; i &gt;= 0; i--){              //i &gt;= 0 sollte schneller als i&lt;number sein
    number_of_value += (array[i] == value);        //Vermeidung des bedingten Sprunges
  }
  return number_of_value;
}
</code></pre>
<p>Es ist Code für einen normalen PC, also nicht embedded oder so.</p>
<p>Ist func2 nennenswert schneller als func1? Kann allgemein gesagt werden, dass das Vermeiden von if´s schnelleren Code bringt? Welche anderen Optimierungsmaßnahmen gibt es sonst noch für dieses Beispiel?</p>
<p>Würd mich freuen, wenn mir wer helfen könnte, meine Performancekenntnisse aufzubessern <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/topic/325258/steigert-das-ersetzen-von-quot-if-quot-s-durch-logische-konstrukte-die-performance</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Jul 2026 03:29:42 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/325258.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 22 Apr 2014 15:12:39 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 15:12:39 GMT]]></title><description><![CDATA[<p>Hallo</p>
<p>Am besten erkläre ich es an einem Beispiel, das zählt, wie oft ein Wert in einem Array vorkommt (mein performancekritisches Problem ist analog dazu)</p>
<pre><code>int func1(int* array, int number, int value){
  int number_of_value = 0;
  for(int i=0; i&lt;number; i++){
    if(array[i] == value)
      number_of_value++;
  }
  return number_of_value;
}

int func2(int* array, int number, int value){
  int number_of_value = 0;
  for(int i = number-1; i &gt;= 0; i--){              //i &gt;= 0 sollte schneller als i&lt;number sein
    number_of_value += (array[i] == value);        //Vermeidung des bedingten Sprunges
  }
  return number_of_value;
}
</code></pre>
<p>Es ist Code für einen normalen PC, also nicht embedded oder so.</p>
<p>Ist func2 nennenswert schneller als func1? Kann allgemein gesagt werden, dass das Vermeiden von if´s schnelleren Code bringt? Welche anderen Optimierungsmaßnahmen gibt es sonst noch für dieses Beispiel?</p>
<p>Würd mich freuen, wenn mir wer helfen könnte, meine Performancekenntnisse aufzubessern <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/2395847</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395847</guid><dc:creator><![CDATA[Senfti]]></dc:creator><pubDate>Tue, 22 Apr 2014 15:12:39 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 15:15:54 GMT]]></title><description><![CDATA[<p>Nein, sollte so wie ich das sehe, keinen Boost geben (nicht keinen nennenswerten, sondern keinen). Denn nun muss der Bool'sche Wert ja in einen Integer umgewandelt werden.</p>
<p>Zumal moderne Rechner solche Schleifen schon ziemlich flott können.</p>
<p>Bist du mal mit einem Profiler an deinen Code gegangen und der hat dir gesagt, dass dort der Performanceflaschenhals liegt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2395848</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395848</guid><dc:creator><![CDATA[Skym0sh0]]></dc:creator><pubDate>Tue, 22 Apr 2014 15:15:54 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 15:31:57 GMT]]></title><description><![CDATA[<p>ok, danke.<br />
Mein Hintergedanke war, dass sich bedingte Sprünge und Pipelining nicht mögen</p>
<p>Dann ist die Variante mit dem if besser, weil das sieht nicht so kryptisch aus <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/2395849</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395849</guid><dc:creator><![CDATA[Senfti]]></dc:creator><pubDate>Tue, 22 Apr 2014 15:31:57 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 15:37:10 GMT]]></title><description><![CDATA[<p>Ich sag mal ganz pauschal: Dein Compiler ist klug genug, so was zu erkennen und zu optimieren. (Wenn du nicht irgendwas ganz komisches benutzt.) Wenn du die Optimierung ausschaltest, kann es vielleicht einen Unterschied machen, aber wen interessiert das?</p>
<p>Die Argumentation mit der Umwandlung des boolschen Wertes in einen Integer kann ich aber nicht nachvollziehen. Der ist doch schon einer.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2395850</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395850</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Tue, 22 Apr 2014 15:37:10 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 16:19:03 GMT]]></title><description><![CDATA[<p>Der Code der da erzeugt wird ist durchaus unterschiedlich, ich habe mal folgende Funktionen zum Vergleichen genommen:</p>
<pre><code>std::uint64_t /*__declspec(noinline) */ count1(const std::int32_t* numbers, std::size_t size, std::int32_t number_to_count)
{
	std::uint64_t counter = 0;

	for (std::size_t i = 0; i != size; ++i)
	{
		if (numbers[i] == number_to_count)
			++counter;
	}

	return counter;
}
</code></pre>
<pre><code>std::uint64_t /* __declspec(noinline) */ count2(const std::int32_t* numbers, std::size_t size, std::int32_t number_to_count)
{
	std::uint64_t counter = 0;

	for (std::size_t i = 0; i != size; ++i)
	{
		counter += numbers[i] == number_to_count;
	}

	return counter;
}
</code></pre>
<p>GCC 4.9 -O3 -std=c++11 für count1:</p>
<pre><code>count1(int const*, unsigned long, int):
	test	rsi, rsi
	je	.L4
	lea	rsi, [rdi+rsi*4]
	xor	eax, eax
.L3:
	cmp	DWORD PTR [rdi], edx
	lea	rcx, [rax+1]
	cmove	rax, rcx
	add	rdi, 4
	cmp	rdi, rsi
	jne	.L3
	rep ret
.L4:
	xor	eax, eax
	ret
</code></pre>
<p>GCC 4.9 -O3 -std=c++11 für count2:</p>
<pre><code>count2(int const*, unsigned long, int):
	test	rsi, rsi
	push	rbx
	je	.L13
	mov	rcx, rdi
	and	ecx, 15
	shr	rcx, 2
	neg	rcx
	and	ecx, 3
	cmp	rcx, rsi
	cmova	rcx, rsi
	cmp	rsi, 5
	ja	.L25
	mov	rcx, rsi
.L3:
	xor	eax, eax
	cmp	DWORD PTR [rdi], edx
	sete	al
	cmp	rcx, 1
	je	.L16
	xor	r8d, r8d
	cmp	DWORD PTR [rdi+4], edx
	sete	r8b
	add	rax, r8
	cmp	rcx, 2
	je	.L17
	xor	r8d, r8d
	cmp	DWORD PTR [rdi+8], edx
	sete	r8b
	add	rax, r8
	cmp	rcx, 3
	je	.L18
	xor	r8d, r8d
	cmp	DWORD PTR [rdi+12], edx
	sete	r8b
	add	rax, r8
	cmp	rcx, 5
	jne	.L19
	xor	r8d, r8d
	cmp	DWORD PTR [rdi+16], edx
	sete	r8b
	add	rax, r8
	mov	r8d, 5
.L5:
	cmp	rsi, rcx
	je	.L2
.L4:
	mov	r11, rsi
	lea	r10, [rsi-1]
	sub	r11, rcx
	lea	r9, [r11-4]
	sub	r10, rcx
	shr	r9, 2
	add	r9, 1
	cmp	r10, 2
	lea	rbx, [0+r9*4]
	jbe	.L7
	mov	DWORD PTR [rsp-4], edx
	pxor	xmm2, xmm2
	movd	xmm6, DWORD PTR [rsp-4]
	pxor	xmm3, xmm3
	movdqa	xmm4, XMMWORD PTR .LC0[rip]
	lea	r10, [rdi+rcx*4]
	pshufd	xmm5, xmm6, 0
	xor	ecx, ecx
.L8:
	movdqa	xmm1, XMMWORD PTR [r10]
	add	rcx, 1
	add	r10, 16
	cmp	r9, rcx
	pcmpeqd	xmm1, xmm5
	pand	xmm1, xmm4
	movdqa	xmm0, xmm1
	punpckldq	xmm1, xmm3
	punpckhdq	xmm0, xmm3
	paddq	xmm2, xmm1
	paddq	xmm2, xmm0
	ja	.L8
	movdqa	xmm0, xmm2
	add	r8, rbx
	psrldq	xmm0, 8
	paddq	xmm0, xmm2
	movq	rcx, xmm0
	add	rax, rcx
	cmp	r11, rbx
	je	.L2
.L7:
	xor	ecx, ecx
	cmp	DWORD PTR [rdi+r8*4], edx
	sete	cl
	add	rax, rcx
	lea	rcx, [r8+1]
	cmp	rsi, rcx
	je	.L2
	cmp	DWORD PTR [rdi+rcx*4], edx
	sete	cl
	add	r8, 2
	movzx	ecx, cl
	add	rax, rcx
	cmp	rsi, r8
	je	.L2
	cmp	DWORD PTR [rdi+r8*4], edx
	sete	dl
	movzx	edx, dl
	add	rax, rdx
.L2:
	pop	rbx
	ret
.L25:
	test	rcx, rcx
	jne	.L3
	xor	r8d, r8d
	xor	eax, eax
	jmp	.L4
.L19:
	mov	r8d, 4
	jmp	.L5
.L16:
	mov	r8d, 1
	jmp	.L5
.L17:
	mov	r8d, 2
	jmp	.L5
.L18:
	mov	r8d, 3
	jmp	.L5
.L13:
	xor	eax, eax
	pop	rbx
	ret
.LC0:
	.long	1
	.long	1
	.long	1
	.long	1
</code></pre>
<p>Also was der GCC sich dabei denkt muss mir auch mal jemand erklären. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /><br />
Bei VS gibt's auch Unterschiede:</p>
<pre><code>std::uint64_t __declspec(noinline) count1(const std::int32_t* numbers, std::size_t size, std::int32_t number_to_count)
{
002312A0  push        ebp  
002312A1  mov         ebp,esp  
002312A3  sub         esp,0Ch  
002312A6  push        esi  
002312A7  push        edi  
002312A8  mov         edi,edx  
002312AA  xorps       xmm0,xmm0  
	std::uint64_t counter = 0;
002312AD  movlpd      qword ptr [counter],xmm0  

	for (std::size_t i = 0; i != size; ++i)
002312B2  xor         esi,esi  
002312B4  mov         edx,dword ptr [ebp-8]  
002312B7  mov         eax,dword ptr [counter]  
002312BA  test        edi,edi  
002312BC  je          count1+31h (02312D1h)  
002312BE  mov         edi,edi  
	{
		if (numbers[i] == number_to_count)
002312C0  cmp         dword ptr [ecx+esi*4],2Ah  
	{
		if (numbers[i] == number_to_count)
002312C4  jne         count1+2Ch (02312CCh)  
			++counter;
002312C6  add         eax,1  
002312C9  adc         edx,0  

	for (std::size_t i = 0; i != size; ++i)
002312CC  inc         esi  
002312CD  cmp         esi,edi  
002312CF  jne         count1+20h (02312C0h)  
	}

	return counter;
}
002312D1  pop         edi  
002312D2  pop         esi  
002312D3  mov         esp,ebp  
002312D5  pop         ebp  
002312D6  ret
</code></pre>
<pre><code>std::uint64_t __declspec(noinline) count2(const std::int32_t* numbers, std::size_t size, std::int32_t number_to_count)
{
002312E0  push        ebp  
002312E1  mov         ebp,esp  
002312E3  sub         esp,18h  
002312E6  push        ebx  
002312E7  push        esi  
002312E8  xorps       xmm0,xmm0  
002312EB  mov         dword ptr [ebp-8],edx  
	std::uint64_t counter = 0;

	for (std::size_t i = 0; i != size; ++i)
002312EE  xor         eax,eax  
002312F0  movlpd      qword ptr [counter],xmm0  
002312F5  mov         ebx,ecx  
002312F7  push        edi  
002312F8  test        edx,edx  
002312FA  je          count2+54h (0231334h)  
002312FC  mov         esi,dword ptr [ebp-10h]  
	std::uint64_t counter = 0;

	for (std::size_t i = 0; i != size; ++i)
002312FF  mov         edi,dword ptr [counter]  
	{
		counter += numbers[i] == number_to_count;
00231302  cmp         dword ptr [ebx+eax*4],2Ah  
00231306  jne         count2+31h (0231311h)  
00231308  mov         ecx,1  
0023130D  xor         edx,edx  
0023130F  jmp         count2+3Fh (023131Fh)  
00231311  xorps       xmm0,xmm0  
00231314  movlpd      qword ptr [counter],xmm0  
00231319  mov         edx,dword ptr [ebp-10h]  
0023131C  mov         ecx,dword ptr [counter]  
0023131F  add         edi,ecx  
00231321  adc         esi,edx  
00231323  inc         eax  
00231324  cmp         eax,dword ptr [ebp-8]  
00231327  jne         count2+22h (0231302h)  
	}

	return counter;
00231329  mov         eax,edi  
0023132B  mov         edx,esi  
}
0023132D  pop         edi  
0023132E  pop         esi  
0023132F  pop         ebx  
00231330  mov         esp,ebp  
00231332  pop         ebp  
00231333  ret  
	}

	return counter;
00231334  mov         eax,dword ptr [counter]  
00231337  mov         edx,dword ptr [ebp-10h]  
}
0023133A  pop         edi  
0023133B  pop         esi  
0023133C  pop         ebx  
0023133D  mov         esp,ebp  
0023133F  pop         ebp  
00231340  ret
</code></pre>
<p>clang 3.3 dagegen generiert bei beiden Funktionen exakt das gleiche: (sorry clang mag keine Intel-Syntax)</p>
<pre><code>.LCPI0_0:
	.quad	4294967295              # 0xffffffff
	.quad	4294967295              # 0xffffffff
.LCPI0_1:
	.quad	1                       # 0x1
	.quad	1                       # 0x1
count2(int const*, unsigned long, int):                         # @count2(int const*, unsigned long, int)
	xorl	%eax, %eax
	testq	%rsi, %rsi
	je	.LBB0_8
	movq	%rsi, %rcx
	andq	$-4, %rcx
	je	.LBB0_2
	movd	%edx, %xmm2
	movlhps	%xmm2, %xmm2            # xmm2 = xmm2[0,0]
	pxor	%xmm0, %xmm0
	xorl	%eax, %eax
	movaps	.LCPI0_0(%rip), %xmm3
	andps	%xmm3, %xmm2
	movdqa	.LCPI0_1(%rip), %xmm4
	pxor	%xmm1, %xmm1
.LBB0_4:                                # %vector.body
	movq	8(%rdi,%rax,4), %xmm5
	pshufd	$16, %xmm5, %xmm6       # xmm6 = xmm5[0,0,1,0]
	pand	%xmm3, %xmm6
	pcmpeqd	%xmm2, %xmm6
	pshufd	$-79, %xmm6, %xmm5      # xmm5 = xmm6[1,0,3,2]
	movq	(%rdi,%rax,4), %xmm7
	pand	%xmm6, %xmm5
	pshufd	$16, %xmm7, %xmm6       # xmm6 = xmm7[0,0,1,0]
	pand	%xmm3, %xmm6
	pcmpeqd	%xmm2, %xmm6
	addq	$4, %rax
	pand	%xmm4, %xmm5
	paddq	%xmm5, %xmm1
	pshufd	$-79, %xmm6, %xmm5      # xmm5 = xmm6[1,0,3,2]
	pand	%xmm6, %xmm5
	pand	%xmm4, %xmm5
	paddq	%xmm5, %xmm0
	cmpq	%rax, %rcx
	jne	.LBB0_4
	jmp	.LBB0_5
.LBB0_2:
	xorl	%ecx, %ecx
	pxor	%xmm0, %xmm0
	pxor	%xmm1, %xmm1
.LBB0_5:                                # %middle.block
	paddq	%xmm0, %xmm1
	movdqa	%xmm1, %xmm0
	punpckhqdq	%xmm0, %xmm0    # xmm0 = xmm0[1,1]
	paddq	%xmm1, %xmm0
	movd	%xmm0, %rax
	cmpq	%rsi, %rcx
	je	.LBB0_8
	subq	%rcx, %rsi
	leaq	(%rdi,%rcx,4), %r8
.LBB0_7:                                # %scalar.ph
	cmpl	%edx, (%r8)
	sete	%cl
	movzbl	%cl, %edi
	addq	%rdi, %rax
	addq	$4, %r8
	decq	%rsi
	jne	.LBB0_7
.LBB0_8:                                # %._crit_edge
	ret
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2395852</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395852</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 22 Apr 2014 16:19:03 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 16:16:57 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Also was der GCC sich dabei denkt muss mir auch mal jemand erklären.</p>
</blockquote>
<p>Er vektorisiert und betrachtet 4 Zahlen gleichzeitig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2395854</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395854</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 22 Apr 2014 16:16:57 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Tue, 22 Apr 2014 23:07:30 GMT]]></title><description><![CDATA[<p>Oh. Ich muss alles zurücknehmen und bin ziemlich überrascht, dass das dabei herauskommt. Auch deshalb, weil gcc 4.8 mit -O2 noch exakt den gleichen Code für beide Varianten erzeugt (mit -O3 dann auch nicht mehr).</p>
<p>Das ist schon seltsam, dass er für die erste Variante nicht mehr die selbe Struktur erkennt. Scheinbar läuft er irgendwo vorher in einen anderen Optimierungspfad -- ersetzt die Verzweigung durch den lea/cmove-Trick -- und findet von da aus die Vektorisierung nicht mehr. Spannend.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2395906</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395906</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Tue, 22 Apr 2014 23:07:30 GMT</pubDate></item><item><title><![CDATA[Reply to Steigert das Ersetzen von &amp;quot;if&amp;quot;´s durch logische Konstrukte die Performance? on Wed, 23 Apr 2014 05:52:10 GMT]]></title><description><![CDATA[<p>Ja, Vektorisierung ist ab -O3 <a href="http://gcc.gnu.org/projects/tree-ssa/vectorization.html#using" rel="nofollow">standardmäßig aktiviert</a>.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2395918</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2395918</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Wed, 23 Apr 2014 05:52:10 GMT</pubDate></item></channel></rss>