Jump to content

    
__inline__

C6x GCC - что скажете? Лучше или хуже чем TI CC 8.3.5 ?

Recommended Posts

@__inline__ а с GCC всё-таки не стали сравнивать?)

Наверное, для честного сравнения нужно самому собрать тулчейн GCC C6x версии 9. Версия 4.y уже устарела.

Share this post


Link to post
Share on other sites
3 часа назад, __inline__ сказал:

Внял рекомендациям jcxz (за что ему громное спасибо! :sun_bespectacled:).  Удалось увеличить производительность на 30...50% (в зависимости от случая).  Оказывается, индексная адресация лучше ложится на конвеер, чем инкременты с указателями.  И однотипные операции лучше дублировать 2 , 4 или 8 раз.  Перестановка действий также может влиять.   И ещё можно не присваивать переменным промежуточный результат - компилятор это видит и оптимизирует сам.

Конечно индексная лучше! Почему? Ведь когда пишете например:

*ptr = x1; ptr++; *ptr = x2; ptr++; *ptr = x3; ptr++; *ptr = x4; ...

то это означает, что для того чтоб можно было выполнить операцию *ptr=x4 нужно до этого выполнить ptr++ перед ней (так как она вычислит исполнительный адрес для *ptr=x4). А чтобы выполнить *ptr=x3 надо также сделать ptr++ до неё. То есть - все операции в этой цепочке оказываются последовательно-зависимыми. Их нельзя выполнять одновременно-параллельно. Конечно умный компилятор может догадаться и превратить все эти ptr++; *ptr=x.. в индексные, посчитав индексы. Но не факт что он так сделает.

А вот индексные обращения к памяти - они будут независимы одна от другой и могут быть легко распараллелены. И не нужно бояться индексов - для них в системе команд процессоров (тем более DSP) есть индексная адресация. Тем более если индексы - const.

Вобщем для оптимизации DSP-кода следует стараться чтобы внутри цикла было как можно меньше зависимых друг от друга операций, которые должны выполняться строго последовательно. Так оптимизатор сможет их лучше упаковать в пакеты параллельных инструкций.

И дублирование - тоже по этой же причине лучше.

Цитата

 _nassert((int)SROMOffset0%32==0);

Вижу - наконец-то стали использовать _nassert(), а я ещё в самом начале, когда Вы только начинали работать с этим ядром, его советовал. :wink:

 

3 часа назад, __inline__ сказал:

Особо радует вот это (несколько инструкций впараллель):

Да, видно что Вы уже очень плотно загрузили ядро  :good:

Share this post


Link to post
Share on other sites

Потестировал этот GCC, получил листинг.  Параллельность есть, но она слабенькая в отличие от TI CC.

Команда:

c6x-uclinux-g++ -S  -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops -march=c674x -O3 -fomit-frame-pointer -ffast-math -fno-rtti -fno-exceptions -Dc6745 -DNDEBUG -c PPU16.cpp

Код:

#include <stdlib.h>

#include "PPU16.h"

#define VRAM_BUFFER 0xC0800000 /* Bank1 SDRAM            */

#define VIDEO_CACHE 0x11800000 /* 240 x 400 pixel buffer */

#define PRUSS_VideoBuffer (*(IO u32*)(PRU1_Data+0x0000))

#define SROM16 (*(u16*)SROMOffset)
#define VRAM16 (*(u16*)VRAMOffset)

u8 *VRAMBuffer=(u8*)VRAM_BUFFER;

const u8 *SROMBuffer; //SROM Buffer - Pointer

u32 SPRITE_PITCH=2048; //Default Sprite Width: 1024 pixel

#define _amem8(x) (*(x))
#define _mem8(x) (*(x))

void PPU16_ClearVRAM(u16 Color)
{
 u64 c=Color|(Color<<16);
 c|=(c<<32);
 u64 * __restrict vb=(u64*)VRAMBuffer;
// #pragma UNROLL(4)
 for(int i=0;i<(SCREEN_WIDTH*SCREEN_HEIGHT)>>2;i++)_amem8(&vb[i])=c;
}

void PPU16_OutOLED(void)
{
 for(int y=0;y<(SCREEN_HEIGHT<<1);y+=8)
 {
  u64 * __restrict vc=(u64*)(VIDEO_CACHE+y);
  u64 * __restrict vb0=(u64*)&VRAMBuffer[((SCREEN_WIDTH-4)<<1)+(SCREEN_WIDTH*y)];
  u64 * __restrict vb1=vb0+(SCREEN_WIDTH>>2);
  u64 * __restrict vb2=vb1+(SCREEN_WIDTH>>2);
  u64 * __restrict vb3=vb2+(SCREEN_WIDTH>>2); 

  for(int x=0;x<(SCREEN_WIDTH>>2);x++)
  {
   _amem8(&vc[(3*(SCREEN_HEIGHT>>2))+(SCREEN_HEIGHT*x)])=((u64)((u16) _amem8(&vb0[-x])     ))|((u64)((u16) _amem8(&vb1[-x])     )<<16)|((u64)((u16) _amem8(&vb2[-x])     )<<32)|((u64)((u16) _amem8(&vb3[-x])     )<<48);
   _amem8(&vc[(2*(SCREEN_HEIGHT>>2))+(SCREEN_HEIGHT*x)])=((u64)((u16)(_amem8(&vb0[-x])>>16)))|((u64)((u16)(_amem8(&vb1[-x])>>16))<<16)|((u64)((u16)(_amem8(&vb2[-x])>>16))<<32)|((u64)((u16)(_amem8(&vb3[-x])>>16))<<48);
   _amem8(&vc[(1*(SCREEN_HEIGHT>>2))+(SCREEN_HEIGHT*x)])=((u64)((u16)(_amem8(&vb0[-x])>>32)))|((u64)((u16)(_amem8(&vb1[-x])>>32))<<16)|((u64)((u16)(_amem8(&vb2[-x])>>32))<<32)|((u64)((u16)(_amem8(&vb3[-x])>>32))<<48);
   _amem8(&vc[(0*(SCREEN_HEIGHT>>2))+(SCREEN_HEIGHT*x)])=((u64)((u16)(_amem8(&vb0[-x])>>48)))|((u64)((u16)(_amem8(&vb1[-x])>>48))<<16)|((u64)((u16)(_amem8(&vb2[-x])>>48))<<32)|((u64)((u16)(_amem8(&vb3[-x])>>48))<<48);
  }
 }
}

 

Даёт такой листинг:

Spoiler

	.file	"PPU16.cpp"
	.c6xabi_attribute Tag_ABI_array_object_alignment, 0
	.c6xabi_attribute Tag_ABI_array_object_align_expected, 0
	.c6xabi_attribute Tag_ABI_stack_align_needed, 0
	.c6xabi_attribute Tag_ABI_stack_align_preserved, 0
	.c6xabi_attribute Tag_ABI_conformance, "1.0"
.text;
	.align	2
	.global	PPU16_ClearVRAM
	.type	PPU16_ClearVRAM, @function
PPU16_ClearVRAM:
		sub	.d2	B15, 8, B15
		stw	.d2t2	B14, *+B15(8)
		ldw	.d2t2	*+B14($DSBT_index(__c6xabi_DSBT_BASE)), B14
	||	extu	.s1	A4, 16, 16, A6
		mvk	.s1	24000, A0
		shl	.s1	A6, 16, A7
		mvc	.s2x	A0, ILC
	||	or	.d1	A6, A7, A4
		shr	.s1	A4, 31, A8
		ldw	.d2t1	*+B14(VRAMBuffer), A3
	||	or	.d1	A8, A4, A5
		nop	4
		sploop	2
.L2:
		stw	.d1t1	A4, *A3
		stw	.d1t1	A5, *+A3(4)
	||	add	.s1	8, A3, A3
		spkernel	1, 0
		ret	.s2	B3
	||	ldw	.d2t2	*+B15(8), B14
	||	add	.l2	8, B15, B15
		nop	5
	;; return occurs
	.size	PPU16_ClearVRAM, .-PPU16_ClearVRAM
	.align	2
	.global	PPU16_OutOLED
	.type	PPU16_OutOLED, @function
PPU16_OutOLED:
		sub	.d2	B15, 8, B15
		stw	.d2t2	B14, *+B15(8)
		ldw	.d2t2	*+B14($DSBT_index(__c6xabi_DSBT_BASE)), B14
	||	mvk	.s1	1440, A24
	||	mvk	.d1	0, A21
	||	mvk	.l1	0, A26
		mvk	.s1	960, A23
		mvk	.s1	480, A22
		mvklh	.s1	4480, A24
		mvklh	.s1	4480, A23
		ldw	.d2t1	*+B14(VRAMBuffer), A25
	||	mvklh	.s1	4480, A22
		mvklh	.s1	4480, A21
		mvk	.s1	60, A2
		nop	2
		addk	.s1	792, A25
.L8:
		mvk	.s1	800, A7
	||	sub	.d1	A2, 1, A2
	||	mv	.l1	A26, A5
		mvk	.s1	1600, A8
	||	add	.d1	A25, A7, A4
	||	mv	.l1	A25, A0
		mvk	.s1	2400, A9
	||	add	.d1	A25, A8, A3
		add	.d1	A25, A9, A6
	||	mvk	.s1	100, A1
.L7:
		ldhu	.d1t1	*A4, A19
	||	add	.l1	A5, A24, A16
	||	add	.s1	A5, A23, A27
		ldhu	.d1t1	*A6, A17
	||	add	.l1	A5, A22, A28
	||	add	.s1	-1, A1, A1
		ldhu	.d1t1	*A3, A18
	||	add	.l1	A5, A21, A29
	||	addk	.s1	1920, A5
		ldhu	.d1t1	*A0, A20
		nop	1
		shl	.s1	A19, 16, A30
		shl	.s1	A17, 16, A7
		or	.d1	A7, A18, A8
		or	.s1	A20, A30, A31
	||	stw	.d1t1	A8, *+A16(4)
		stw	.d1t1	A31, *A16
		ldw	.d1t1	*A4, A9
		ldw	.d1t1	*A3, A20
		ldw	.d1t1	*A0, A18
		ldw	.d1t1	*A6, A16
		nop	1
		clr	.s1	A9, 0, 15, A19
		shru	.s1	A20, 16, A17
		shru	.s1	A18, 16, A30
		clr	.s1	A16, 0, 15, A7
	||	or	.d1	A30, A19, A31
		or	.s1	A7, A17, A8
	||	stw	.d1t1	A31, *A27
		stw	.d1t1	A8, *+A27(4)
		ldhu	.d1t1	*+A4(4), A27
		ldhu	.d1t1	*+A6(4), A9
		ldhu	.d1t1	*+A3(4), A20
		ldhu	.d1t1	*+A0(4), A18
		nop	1
		shl	.s1	A27, 16, A16
		shl	.s1	A9, 16, A17
		or	.d1	A17, A20, A30
		or	.s1	A18, A16, A19
	||	stw	.d1t1	A30, *+A28(4)
		stw	.d1t1	A19, *A28
		ldhu	.d1t1	*+A4(6), A28
	||	add	.s1	-8, A4, A4
		ldhu	.d1t1	*+A6(6), A8
	||	add	.s1	-8, A6, A6
		ldhu	.d1t1	*+A3(6), A31
	||	add	.s1	-8, A3, A3
		ldhu	.d1t1	*+A0(6), A7
	||	add	.s1	-8, A0, A0
	[A1]	b	.s1	.L7
		shl	.s1	A28, 16, A27
		shl	.s1	A8, 16, A18
		or	.d1	A18, A31, A9
		stw	.d1t1	A9, *+A29(4)
	||	or	.s1	A7, A27, A20
		stw	.d1t1	A20, *A29
	;; condjump to .L7 occurs
	[A2]	b	.s1	.L8
	||	add	.d1	A26, 8, A26
		addk	.s1	3200, A25
		nop	4
	;; condjump to .L8 occurs
		ret	.s2	B3
	||	ldw	.d2t2	*+B15(8), B14
	||	add	.l2	8, B15, B15
		nop	5
	;; return occurs
	.size	PPU16_OutOLED, .-PPU16_OutOLED
	.global	VRAMBuffer
	.section	.neardata,"aw",@progbits
	.align	2
	.type	VRAMBuffer, @object
	.size	VRAMBuffer, 4
VRAMBuffer:
	.long	-1065353216
	.global	SROMBuffer
	.section	.bss,"aw",@nobits
	.align	2
	.type	SROMBuffer, @object
	.size	SROMBuffer, 4
SROMBuffer:
	.zero	4
	.global	SPRITE_PITCH
	.section	.neardata
	.align	2
	.type	SPRITE_PITCH, @object
	.size	SPRITE_PITCH, 4
SPRITE_PITCH:
	.long	2048
	.ident	"GCC: (Sourcery CodeBench Lite 4.5-124) 4.5.1"

 

 

Слабовато.   И _mem8, _amem8 не знает, пришлось задефайнить разыменовыванием указателей, что не совсем верно.

Share this post


Link to post
Share on other sites
6 минут назад, __inline__ сказал:

Потестировал этот GCC

Он уже старенький :) Собрать бы GCC 9 или даже из транка GCC 10 на праздниках под TI и посмотреть. Вряд ли кто-то ещё выкладывает нынче бинарные сборки тулчейна. Но, думаю, ситуация не сильно изменится по сравнению исо старыми версиями.

9 минут назад, __inline__ сказал:

Даёт такой листинг:

Класс! Спасибо за исследование. Очень интересно.

Share this post


Link to post
Share on other sites
1 hour ago, Grizzly said:

Класс! Спасибо за исследование. Очень интересно.

Да не за что )) Вы можете это проделать сами очень легко - ничего сложного !

Edited by __inline__

Share this post


Link to post
Share on other sites
On 1/3/2020 at 2:36 PM, __inline__ said:

Да не за что )) Вы можете это проделать сами очень легко - ничего сложного !

 

Здравствуйте!

Можете порекомендовать dsp процессоры от TI для видеообработки(как минимум фильтрация двумерная, обработка гистограммы, fft,wavelet и т.д.)?

И еще, matlab/simulink может генерировать c/c++ коды из своих кодов/блоков. Можно ли этот код скормить (не вдаваясь в подробности этих dsp) для code composer studio? у матлаба был "Embedded Coder Support Package for Texas Instruments C6000 DSPs" до 2016, а сейчас у них нет поддержки этих c6000. я с этими сигнальниками не имел дела, code composer studio сам может оптимизировать код?

Share this post


Link to post
Share on other sites
1 час назад, Niyaz сказал:

я с этими сигнальниками не имел дела, code composer studio сам может оптимизировать код?

Уже древний CCS3.3 для 6000-го семейства создавал вполне оптимальный код из си-исходника. Программировать на ассемблере, для оптимизации по скорости, уже тогда не было необходимости.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.