Производительность FPU Cortex-M4

Нигде не нашел информации о количество мегафлопсов у Cortex-M4 c аппаратной плавающей точкой. Сделал свой тест используя stm32f4discovery и кусочек кода фильтра Калмана для двигателя.


Взял вот такой код, который умножает матрицы размером 5x5, количество операций я насчитал 525, отдельно учитывал сложения и умножения. Исходные данные берутся из таймера, записываются в глобальную переменную, компилятор не должен уклонится от генерации кода и слишком все упростить.

#include "hal/cmsis/stm32f4xx.h"

static void
mTrans(float *X, const float *A, int M, int N)
{
	int		i, j;

	for (i = 0; i < M; ++i)
		for (j = 0; j < N; ++j) {

			X[j * M + i] = A[i * N + j];
		}
}

static void
mMul(float *X, const float *A, const float *B, int M, int N, int K)
{
	int		i, j, k;
	float		s;

	for (i = 0; i < M; ++i)
		for (j = 0; j < N; ++j) {

			s = 0.f;
			for (k = 0; k < K; ++k)
				s += A[i * K + k] * B[k * N + j];

			X[i * N + j] = s;
		}
}

static float		P[25];

void sKF()
{
	float		A[25], AT[25], AP[25];
	int		i, j;
	int		T0, T1;
	float		dT;

	for (i = 0; i < 5; ++i)
		for (j = 0; j < 5; ++j) {

			P[i * 5 + j] = 1.f / (float) SysTick->VAL;
		}

	for (i = 0; i < 5; ++i)
		for (j = 0; j < 5; ++j) {

			A[i * 5 + j] = 1.f / (float) SysTick->VAL;
		}

	T0 = SysTick->VAL;

	mTrans(AT, A, 5, 5);
	mMul(AP, A, P, 5, 5, 5);
	mMul(P, AP, AT, 5, 5, 5);

	T1 = SysTick->VAL;

	printf("TICK (%i %i) %i \r\n", T0, T1, T0 - T1);
}


Весь код здесь.

Тест делался как я уже говорил на stm32f4discovery, частота 168МГц. Код находился в RAM либо во FLASH, переменные в RAM, стек в CCM. Посторонних задач не было, только uart, led и таймер.

GCC (RAM/FLASH):
-O2 4709/3677 ticks (2196 bytes) 19/23 MFLOPS
-O3 1658/1473 ticks (3596 bytes) 53/60 MFLOPS
-Os 5615/3714 ticks (1908 bytes) 16/24 MFLOPS

Clang (RAM):
-O2 2917 ticks (2664 bytes) 30 MFLOPS
-O3 1770 ticks (3304 bytes) 50 MFLOPS
-Os 5867 ticks (2496 bytes) 15 MFLOPS


На тестах из FLASH первый запуск был на 10-20 тактов дольше, дальше стабильно. Из RAM стабильно всегда. Итого для такой тактовой частоты получаем одну операцию с float на ~3 такта. И наверно можно выдавить еще скорости, положить переменные в CCM, развернуть циклы вручную, учесть разреженность матриц.

Неплохо, но для моей задачи мало. Похоже снова придется отказатся от фильтра Калмана и пойти на третий круг.

Добавка
Сделал еще один тест, с более развернутым кодом. Теперь простое одиночное уменожение двух матриц размера 5 на 5. Можете посчитать, для этого нужно 125 умножений и 100 сложений, всего 225 операций. На это количество операций я и буду пересчитывать такты во флопсы.

float			P[25];

void sKF()
{
	float		A[25], B[25];
	int		j, T0, T1;
	float		dT;

	for (j = 0; j < 25; ++j)
		A[j] = 1.f / (float) SysTick->VAL;

	for (j = 0; j < 25; ++j)
		B[j] = 1.f / (float) SysTick->VAL;

	T0 = SysTick->VAL;
	__DSB();

	P[0] = A[0] * B[0] + A[1] * B[5] + A[2] * B[10] + A[3] * B[15] + A[4] * B[20];
	P[1] = A[0] * B[1] + A[1] * B[6] + A[2] * B[11] + A[3] * B[16] + A[4] * B[21];
	P[2] = A[0] * B[2] + A[1] * B[7] + A[2] * B[12] + A[3] * B[17] + A[4] * B[22];
	P[3] = A[0] * B[3] + A[1] * B[8] + A[2] * B[13] + A[3] * B[18] + A[4] * B[23];
	P[4] = A[0] * B[4] + A[1] * B[9] + A[2] * B[14] + A[3] * B[19] + A[4] * B[24];

	P[5] = A[5] * B[0] + A[6] * B[5] + A[7] * B[10] + A[8] * B[15] + A[9] * B[20];
	P[6] = A[5] * B[1] + A[6] * B[6] + A[7] * B[11] + A[8] * B[16] + A[9] * B[21];
	P[7] = A[5] * B[2] + A[6] * B[7] + A[7] * B[12] + A[8] * B[17] + A[9] * B[22];
	P[8] = A[5] * B[3] + A[6] * B[8] + A[7] * B[13] + A[8] * B[18] + A[9] * B[23];
	P[9] = A[5] * B[4] + A[6] * B[9] + A[7] * B[14] + A[8] * B[19] + A[9] * B[24];

	P[10] = A[10] * B[0] + A[11] * B[5] + A[12] * B[10] + A[13] * B[15] + A[14] * B[20];
	P[11] = A[10] * B[1] + A[11] * B[6] + A[12] * B[11] + A[13] * B[16] + A[14] * B[21];
	P[12] = A[10] * B[2] + A[11] * B[7] + A[12] * B[12] + A[13] * B[17] + A[14] * B[22];
	P[13] = A[10] * B[3] + A[11] * B[8] + A[12] * B[13] + A[13] * B[18] + A[14] * B[23];
	P[14] = A[10] * B[4] + A[11] * B[9] + A[12] * B[14] + A[13] * B[19] + A[14] * B[24];

	P[15] = A[15] * B[0] + A[16] * B[5] + A[17] * B[10] + A[18] * B[15] + A[19] * B[20];
	P[16] = A[15] * B[1] + A[16] * B[6] + A[17] * B[11] + A[18] * B[16] + A[19] * B[21];
	P[17] = A[15] * B[2] + A[16] * B[7] + A[17] * B[12] + A[18] * B[17] + A[19] * B[22];
	P[18] = A[15] * B[3] + A[16] * B[8] + A[17] * B[13] + A[18] * B[18] + A[19] * B[23];
	P[19] = A[15] * B[4] + A[16] * B[9] + A[17] * B[14] + A[18] * B[19] + A[19] * B[24];

	P[20] = A[20] * B[0] + A[21] * B[5] + A[22] * B[10] + A[23] * B[15] + A[24] * B[20];
	P[21] = A[20] * B[1] + A[21] * B[6] + A[22] * B[11] + A[23] * B[16] + A[24] * B[21];
	P[22] = A[20] * B[2] + A[21] * B[7] + A[22] * B[12] + A[23] * B[17] + A[24] * B[22];
	P[23] = A[20] * B[3] + A[21] * B[8] + A[22] * B[13] + A[23] * B[18] + A[24] * B[23];
	P[24] = A[20] * B[4] + A[21] * B[9] + A[22] * B[14] + A[23] * B[19] + A[24] * B[24];

	__DSB();
	T1 = SysTick->VAL;

	printf("TICK (%i %i) %i \r\n", T0, T1, T0 - T1);
}


GCC (FLASH):
-O3 475 ticks 80 MFLOPS (~2.1 tick./op.)

Clang (FLASH):
-O3 540 ticks 70 MFLOPS (~2.4 tick./op.)


Clang выдал код без инструкции vmla, все только на vmul и vadd, возможно из-за этого результат хуже. Ну и вот код GCC от dsb до dsb, если кому будет не лень.

54:	6891      	ldr	r1, [r2, #8]
  56:	f3bf 8f4f 	dsb	sy
  5a:	eddd 5a01 	vldr	s11, [sp, #4]
  5e:	ed9d 6a1e 	vldr	s12, [sp, #120]	; 0x78
  62:	ed9d 0a00 	vldr	s0, [sp]
  66:	ed9d 4a19 	vldr	s8, [sp, #100]	; 0x64
  6a:	eddd 6a1f 	vldr	s13, [sp, #124]	; 0x7c
  6e:	ed9d 7a20 	vldr	s14, [sp, #128]	; 0x80
  72:	eddd 7a21 	vldr	s15, [sp, #132]	; 0x84
  76:	eddd fa22 	vldr	s31, [sp, #136]	; 0x88
  7a:	eddd 4a1a 	vldr	s9, [sp, #104]	; 0x68
  7e:	ed9d 5a1b 	vldr	s10, [sp, #108]	; 0x6c
  82:	eddd da1d 	vldr	s27, [sp, #116]	; 0x74
  86:	ed9d ea1c 	vldr	s28, [sp, #112]	; 0x70
  8a:	ee25 2a86 	vmul.f32	s4, s11, s12
  8e:	ee65 2aa6 	vmul.f32	s5, s11, s13
  92:	ee25 3a87 	vmul.f32	s6, s11, s14
  96:	ee00 2a04 	vmla.f32	s4, s0, s8
  9a:	ee65 3aa7 	vmul.f32	s7, s11, s15
  9e:	ee65 5aaf 	vmul.f32	s11, s11, s31
  a2:	eddd 0a02 	vldr	s1, [sp, #8]
  a6:	eddd ca23 	vldr	s25, [sp, #140]	; 0x8c
  aa:	ee40 2a24 	vmla.f32	s5, s0, s9
  ae:	ee00 3a05 	vmla.f32	s6, s0, s10
  b2:	ee40 3a0e 	vmla.f32	s7, s0, s28
  b6:	ee40 5a2d 	vmla.f32	s11, s0, s27
  ba:	eddd ba25 	vldr	s23, [sp, #148]	; 0x94
  be:	ed9d ba26 	vldr	s22, [sp, #152]	; 0x98
  c2:	eddd aa27 	vldr	s21, [sp, #156]	; 0x9c
  c6:	ed9d 0a24 	vldr	s0, [sp, #144]	; 0x90
  ca:	ee00 2aac 	vmla.f32	s4, s1, s25
  ce:	ed9d 1a03 	vldr	s2, [sp, #12]
  d2:	ee40 2a80 	vmla.f32	s5, s1, s0
  d6:	ee00 3aab 	vmla.f32	s6, s1, s23
  da:	ee40 3a8b 	vmla.f32	s7, s1, s22
  de:	ee40 5aaa 	vmla.f32	s11, s1, s21
  e2:	eddd 0a28 	vldr	s1, [sp, #160]	; 0xa0
  e6:	eddd 9a29 	vldr	s19, [sp, #164]	; 0xa4
  ea:	ed9d 9a2a 	vldr	s18, [sp, #168]	; 0xa8
  ee:	eddd 8a2b 	vldr	s17, [sp, #172]	; 0xac
  f2:	ee01 2a20 	vmla.f32	s4, s2, s1
  f6:	eddd 1a04 	vldr	s3, [sp, #16]
  fa:	ed9d 0a2c 	vldr	s0, [sp, #176]	; 0xb0
  fe:	eddd 0a2d 	vldr	s1, [sp, #180]	; 0xb4
 102:	ee41 2a29 	vmla.f32	s5, s2, s19
 106:	ee01 3a09 	vmla.f32	s6, s2, s18
 10a:	ee41 3a28 	vmla.f32	s7, s2, s17
 10e:	ee01 2aa0 	vmla.f32	s4, s3, s1
 112:	ee41 5a00 	vmla.f32	s11, s2, s0
 116:	eddd 0a30 	vldr	s1, [sp, #192]	; 0xc0
 11a:	ed9d 1a2e 	vldr	s2, [sp, #184]	; 0xb8
 11e:	ed9d 0a2f 	vldr	s0, [sp, #188]	; 0xbc
 122:	ee41 2a81 	vmla.f32	s5, s3, s2
 126:	ee01 3a80 	vmla.f32	s6, s3, s0
 12a:	ee41 3aa0 	vmla.f32	s7, s3, s1
 12e:	f240 0300 	movw	r3, #0
 132:	f2c0 0300 	movt	r3, #0
 136:	ed9d 1a31 	vldr	s2, [sp, #196]	; 0xc4
 13a:	ed83 2a00 	vstr	s4, [r3]
 13e:	edc3 2a01 	vstr	s5, [r3, #4]
 142:	ed83 3a02 	vstr	s6, [r3, #8]
 146:	edc3 3a03 	vstr	s7, [r3, #12]
 14a:	eddd 0a06 	vldr	s1, [sp, #24]
 14e:	ee41 5a81 	vmla.f32	s11, s3, s2
 152:	eddd 1a05 	vldr	s3, [sp, #20]
 156:	ee26 aaa0 	vmul.f32	s20, s13, s1
 15a:	ee04 aaa1 	vmla.f32	s20, s9, s3
 15e:	ed9d 2a07 	vldr	s4, [sp, #28]
 162:	ed9d 0a24 	vldr	s0, [sp, #144]	; 0x90
 166:	ee26 ca20 	vmul.f32	s24, s12, s1
 16a:	ee00 aa02 	vmla.f32	s20, s0, s4
 16e:	ee27 8a20 	vmul.f32	s16, s14, s1
 172:	ee27 0aa0 	vmul.f32	s0, s15, s1
 176:	ee6f 0aa0 	vmul.f32	s1, s31, s1
 17a:	ee04 ca21 	vmla.f32	s24, s8, s3
 17e:	ee05 8a21 	vmla.f32	s16, s10, s3
 182:	ee0e 0a21 	vmla.f32	s0, s28, s3
 186:	ee4d 0aa1 	vmla.f32	s1, s27, s3
 18a:	ee0c ca82 	vmla.f32	s24, s25, s4
 18e:	ee0b 8a82 	vmla.f32	s16, s23, s4
 192:	ee0b 0a02 	vmla.f32	s0, s22, s4
 196:	ee4a 0a82 	vmla.f32	s1, s21, s4
 19a:	eddd 2a08 	vldr	s5, [sp, #32]
 19e:	ed9d 3a0b 	vldr	s6, [sp, #44]	; 0x2c
 1a2:	ed9d 1a28 	vldr	s2, [sp, #160]	; 0xa0
 1a6:	ed9d 2a2c 	vldr	s4, [sp, #176]	; 0xb0
 1aa:	eddd 3a0a 	vldr	s7, [sp, #40]	; 0x28
 1ae:	ed9d fa15 	vldr	s30, [sp, #84]	; 0x54
 1b2:	edc3 5a04 	vstr	s11, [r3, #16]
 1b6:	eddd 5a10 	vldr	s11, [sp, #64]	; 0x40
 1ba:	ed9d da14 	vldr	s26, [sp, #80]	; 0x50
 1be:	eddd ea0f 	vldr	s29, [sp, #60]	; 0x3c
 1c2:	ee01 ca22 	vmla.f32	s24, s2, s5
 1c6:	ee09 aaa2 	vmla.f32	s20, s19, s5
 1ca:	ee09 8a22 	vmla.f32	s16, s18, s5
 1ce:	ee26 1a03 	vmul.f32	s2, s12, s6
 1d2:	ee08 0aa2 	vmla.f32	s0, s17, s5
 1d6:	ee42 0a22 	vmla.f32	s1, s4, s5
 1da:	ee66 1a83 	vmul.f32	s3, s13, s6
 1de:	ee27 2a03 	vmul.f32	s4, s14, s6
 1e2:	ee67 2a83 	vmul.f32	s5, s15, s6
 1e6:	ee2f 3a83 	vmul.f32	s6, s31, s6
 1ea:	ee04 1a23 	vmla.f32	s2, s8, s7
 1ee:	ee44 1aa3 	vmla.f32	s3, s9, s7
 1f2:	ee05 2a23 	vmla.f32	s4, s10, s7
 1f6:	ee4e 2a23 	vmla.f32	s5, s28, s7
 1fa:	ee0d 3aa3 	vmla.f32	s6, s27, s7
 1fe:	ee66 3a25 	vmul.f32	s7, s12, s11
 202:	ee26 6a0f 	vmul.f32	s12, s12, s30
 206:	ee44 3a2e 	vmla.f32	s7, s8, s29
 20a:	ee04 6a0d 	vmla.f32	s12, s8, s26
 20e:	ee26 4aa5 	vmul.f32	s8, s13, s11
 212:	ee66 6a8f 	vmul.f32	s13, s13, s30
 216:	ee04 4aae 	vmla.f32	s8, s9, s29
 21a:	ee44 6a8d 	vmla.f32	s13, s9, s26
 21e:	ee67 4a25 	vmul.f32	s9, s14, s11
 222:	ee27 7a0f 	vmul.f32	s14, s14, s30
 226:	ee45 4a2e 	vmla.f32	s9, s10, s29
 22a:	ee05 7a0d 	vmla.f32	s14, s10, s26
 22e:	ee27 5aa5 	vmul.f32	s10, s15, s11
 232:	ee6f 5aa5 	vmul.f32	s11, s31, s11
 236:	ee67 7a8f 	vmul.f32	s15, s15, s30
 23a:	ee2f fa8f 	vmul.f32	s30, s31, s30
 23e:	ee4d 5aae 	vmla.f32	s11, s27, s29
 242:	ee4e 7a0d 	vmla.f32	s15, s28, s26
 246:	ee0d fa8d 	vmla.f32	s30, s27, s26
 24a:	ed9d da0c 	vldr	s26, [sp, #48]	; 0x30
 24e:	eddd da24 	vldr	s27, [sp, #144]	; 0x90
 252:	ee0e 5a2e 	vmla.f32	s10, s28, s29
 256:	ee0c 1a8d 	vmla.f32	s2, s25, s26
 25a:	ee4d 1a8d 	vmla.f32	s3, s27, s26
 25e:	ee0b 2a8d 	vmla.f32	s4, s23, s26
 262:	ee4b 2a0d 	vmla.f32	s5, s22, s26
 266:	ee0a 3a8d 	vmla.f32	s6, s21, s26
 26a:	ed9d da11 	vldr	s26, [sp, #68]	; 0x44
 26e:	ee4c 3a8d 	vmla.f32	s7, s25, s26
 272:	ee0d 4a8d 	vmla.f32	s8, s27, s26
 276:	ee4b 4a8d 	vmla.f32	s9, s23, s26
 27a:	ee0b 5a0d 	vmla.f32	s10, s22, s26
 27e:	ee4a 5a8d 	vmla.f32	s11, s21, s26
 282:	ed9d da16 	vldr	s26, [sp, #88]	; 0x58
 286:	ee0c 6a8d 	vmla.f32	s12, s25, s26
 28a:	ee4d 6a8d 	vmla.f32	s13, s27, s26
 28e:	ee0b 7a8d 	vmla.f32	s14, s23, s26
 292:	ee4b 7a0d 	vmla.f32	s15, s22, s26
 296:	ee0a fa8d 	vmla.f32	s30, s21, s26
 29a:	ed9d ba12 	vldr	s22, [sp, #72]	; 0x48
 29e:	eddd aa17 	vldr	s21, [sp, #92]	; 0x5c
 2a2:	eddd ca28 	vldr	s25, [sp, #160]	; 0xa0
 2a6:	eddd da2c 	vldr	s27, [sp, #176]	; 0xb0
 2aa:	eddd ba0d 	vldr	s23, [sp, #52]	; 0x34
 2ae:	ee4c 3a8b 	vmla.f32	s7, s25, s22
 2b2:	ee0c 6aaa 	vmla.f32	s12, s25, s21
 2b6:	ee09 4a8b 	vmla.f32	s8, s19, s22
 2ba:	ee49 6aaa 	vmla.f32	s13, s19, s21
 2be:	ee49 4a0b 	vmla.f32	s9, s18, s22
 2c2:	ee09 7a2a 	vmla.f32	s14, s18, s21
 2c6:	ee08 5a8b 	vmla.f32	s10, s17, s22
 2ca:	ee4d 5a8b 	vmla.f32	s11, s27, s22
 2ce:	ee48 7aaa 	vmla.f32	s15, s17, s21
 2d2:	ed9d ba09 	vldr	s22, [sp, #36]	; 0x24
 2d6:	ee0d faaa 	vmla.f32	s30, s27, s21
 2da:	eddd aa2d 	vldr	s21, [sp, #180]	; 0xb4
 2de:	ee0c 1aab 	vmla.f32	s2, s25, s23
 2e2:	ee0a ca8b 	vmla.f32	s24, s21, s22
 2e6:	eddd ca2f 	vldr	s25, [sp, #188]	; 0xbc
 2ea:	eddd aa31 	vldr	s21, [sp, #196]	; 0xc4
 2ee:	ee49 1aab 	vmla.f32	s3, s19, s23
 2f2:	ee09 2a2b 	vmla.f32	s4, s18, s23
 2f6:	ee48 2aab 	vmla.f32	s5, s17, s23
 2fa:	ee0d 3aab 	vmla.f32	s6, s27, s23
 2fe:	eddd ba2e 	vldr	s23, [sp, #184]	; 0xb8
 302:	eddd da30 	vldr	s27, [sp, #192]	; 0xc0
 306:	eddd 9a0e 	vldr	s19, [sp, #56]	; 0x38
 30a:	ed9d 9a13 	vldr	s18, [sp, #76]	; 0x4c
 30e:	eddd 8a18 	vldr	s17, [sp, #96]	; 0x60
 312:	ee0b aa8b 	vmla.f32	s20, s23, s22
 316:	ee0c 8a8b 	vmla.f32	s16, s25, s22
 31a:	ee0d 0a8b 	vmla.f32	s0, s27, s22
 31e:	ee4a 0a8b 	vmla.f32	s1, s21, s22
 322:	ed9d ba2d 	vldr	s22, [sp, #180]	; 0xb4
 326:	ee4b 1aa9 	vmla.f32	s3, s23, s19
 32a:	ee0b 1a29 	vmla.f32	s2, s22, s19
 32e:	ee0c 2aa9 	vmla.f32	s4, s25, s19
 332:	ee4d 2aa9 	vmla.f32	s5, s27, s19
 336:	ee0a 3aa9 	vmla.f32	s6, s21, s19
 33a:	ee4b 3a09 	vmla.f32	s7, s22, s18
 33e:	ee0b 6a28 	vmla.f32	s12, s22, s17
 342:	ee0b 4a89 	vmla.f32	s8, s23, s18
 346:	ee4b 6aa8 	vmla.f32	s13, s23, s17
 34a:	ee4c 4a89 	vmla.f32	s9, s25, s18
 34e:	ee0c 7aa8 	vmla.f32	s14, s25, s17
 352:	ee0d 5a89 	vmla.f32	s10, s27, s18
 356:	ee4a 5a89 	vmla.f32	s11, s21, s18
 35a:	ee4d 7aa8 	vmla.f32	s15, s27, s17
 35e:	ee0a faa8 	vmla.f32	s30, s21, s17
 362:	ed83 ca05 	vstr	s24, [r3, #20]
 366:	ed83 aa06 	vstr	s20, [r3, #24]
 36a:	ed83 8a07 	vstr	s16, [r3, #28]
 36e:	ed83 0a08 	vstr	s0, [r3, #32]
 372:	edc3 0a09 	vstr	s1, [r3, #36]	; 0x24
 376:	ed83 1a0a 	vstr	s2, [r3, #40]	; 0x28
 37a:	edc3 1a0b 	vstr	s3, [r3, #44]	; 0x2c
 37e:	ed83 2a0c 	vstr	s4, [r3, #48]	; 0x30
 382:	edc3 2a0d 	vstr	s5, [r3, #52]	; 0x34
 386:	ed83 3a0e 	vstr	s6, [r3, #56]	; 0x38
 38a:	edc3 3a0f 	vstr	s7, [r3, #60]	; 0x3c
 38e:	ed83 4a10 	vstr	s8, [r3, #64]	; 0x40
 392:	edc3 4a11 	vstr	s9, [r3, #68]	; 0x44
 396:	ed83 5a12 	vstr	s10, [r3, #72]	; 0x48
 39a:	edc3 5a13 	vstr	s11, [r3, #76]	; 0x4c
 39e:	ed83 6a14 	vstr	s12, [r3, #80]	; 0x50
 3a2:	edc3 6a15 	vstr	s13, [r3, #84]	; 0x54
 3a6:	ed83 7a16 	vstr	s14, [r3, #88]	; 0x58
 3aa:	edc3 7a17 	vstr	s15, [r3, #92]	; 0x5c
 3ae:	ed83 fa18 	vstr	s30, [r3, #96]	; 0x60
 3b2:	f3bf 8f4f 	dsb	sy
 3b6:	6892      	ldr	r2, [r2, #8]


Пробовал включить remap в SYSCFG->MEMRMP но скорость выполнения кода из RAM не изменилась, она ниже чем из флеша.
  • +4
  • 25 ноября 2014, 20:58
  • amaora

Комментарии (39)

RSS свернуть / развернуть
Если оценивать ядро — не лучше ли было на асме тест писать? Или интересует именно производительность кода на С?
+1
  • avatar
  • Vga
  • 25 ноября 2014, 21:17
Его интересует под свою задачу посмотреть, как я понимаю.
0
Да, неудачно назвал пост. Интересует С и как хорошо компиляторы справляются. То есть ближе к реальности.
+1
IAR почему не смотрели?
0
И Keil заодно.
0
Как-то не интересовался никогда, как и на каких условиях их можно получить. Есть ли линуксовая версия. И наверно еще какие-то компиляторы есть, сравнить конечно было бы интересно.
0
На рутрекере скачать, очевидно же!
А вообще есть бесплатный вариант кейла и иар кикстарт. АФАЙК и то и то только под винду.
0
Так и просят сравнить основные компиляторы.
ЗЫ. Подозреваю что интерес к Clang'у на уровне погрешности.
0
Подозреваю что интерес к Clang'у на уровне погрешности
Да ну! Как бы не получилось так, что многие ARM-мэны резко не перескочили в следующем году с GCC на Clang, т.е. ломанный ARM DS-5.
-1
И много народу этим пользуется? В основном все на IAR'е и Eclipce сидят вроде
0
В основном все на IAR'е
Ещё Keil есть.
Eclipce сидят
Eclipse — не компилятор вообще, а IDE поддерживающая разные языки (Java/PHP/C++ и тд). Может и для CLang версию сделают.
0
Интересный текст на опеннете:
ARM Compiler 6 полностью избавлен от компонентов под лицензией GPL, что позволяет потребителям не заботиться об обеспечении лицензионной чистоты производных работ.


Я недопонял — он избавлен от GPL пользу прориетарных лицензий, или все-таки LGPL? :D
0
Интересненько. Только вот не пойму: почему Вы под свою задачу полноценный процессор не используете?
0
Он же вроде контроллером моделистского BLDC занимается, а ставить туда i7 как-то…
Да и эти МК уже вполне полноценный процессор, хотя для данной задачи, возможно, лучше бы подошел DSP.
0
Он же вроде контроллером моделистского BLDC занимается, а ставить туда i7 как-то…
-1
0
Неплохо, но для моей задачи мало.
Можно поподробнее о задаче? Всё же 50 мегафлопсов, мечта настолки двадцатилетней давности.
0
Да вот еще посчитал, может быть и умещается. Фильтр на 4-5 переменных скорее всего уместиться, но хочется на 7-9 переменных, с адаптацией к изменению сопротивления обмотки, потока от магнитов, параметров магнитопровода. Подробнее надо отдельно рассказывать. Недостаток производительности от того, что сигналы быстро изменяющиеся. Частота фильтра как минимум 20кГц. То есть надо все успевать за ~8к тактов, а лучше за 4к.
0
IMHO, в коде многовато «шума» в виде целочисленных умножений, которые негативно влияют на производительность. Скажем, во всех циклах выражения типа i*N/i*K можно вынести из тела цикла. Да и вообще мне не совсем понятно зачем было реализовывать адресную арифметику руками и использовать одномерные массивы, при том, что работа идет с матрицами.

Кстати, насколько я понимаю, задача может вполне вписаться в DSP extension Cortex-M4 (у stm-ок оно тоже есть). Возможно имеет смысл покопать в этом направлении, все-таки 16/32 умножение-сложение за один такт или два 16/16 умножения-сложения за один такт это весьма немало.
+3
  • avatar
  • evsi
  • 26 ноября 2014, 11:12
Это черновой вариант для отладки. Окончательный вариант должен учитывать разреженность и симметричность матриц. Ну и циклы все развернуты будут.

Для компиляторов, мне кажется, давно уже не имеют значения такие мелочи как размерность массива и вручную введенная индексация. Они распознают, что выражения эквивалентны, и неизменное слагаемое за цикл вынесут.

С DSP extension, там целые числа, фильтр Калмана на них переложить не просто. Там же матрица ковариации, а в ней легко могут быть в одном элементе 10^3 а в другом 10^-8. А еще сколько с ними всякой возни (выбрать правильно диапазон, следить за переполнением), даже без фильтра.
0
Это черновой вариант для отладки.
Я понимаю. Я больше к тому, что на таком коде сложно делать оценки производительности.
Для компиляторов, мне кажется, давно уже не имеют значения такие мелочи как размерность массива и вручную введенная индексация. Они распознают, что выражения эквивалентны, и неизменное слагаемое за цикл вынесут.
Возможно. Но, как по мне, не стоит нагружать компилятор без необходимости. Тем более, что двухмерный массив и читать и понимать проще.
0
А с какой опцией -mfloat-abi компилировалось, 'softfp' или 'hard'? Исходя из моей практики, 'hard' даёт на 5-10% более быстрый код.
0
А с какой опцией -mfloat-abi компилировалось, 'softfp' или 'hard'?
Попробовал собрать проект с опцией 'hard' — вообще не собралось… Что бы это значило? Тулчайн (или его либы) не поддерживает данную опцию?
Тулчайн — Yagarto.
0
Скорее всего нет либ, собранных для 'hard'. Можно взять какую-нибудь сборку с launchpad.net/gcc-arm-embedded/+download — там с поддержкой 'hard' собрано.
0
Скорее всего нет либ,
Да, наверное.
'hard' даёт на 5-10% более быстрый код.
Не слишком большая разница… Интересно почему так. Чем эти опции отличаются?
0
0
там в комментах ещё ценное есть
0
Линковать надо тоже с опцией hard, у меня под gcc-arm-none-eabi собирается с -hard.
0
Спасибо, попробую.
Линковать надо тоже с опцией hard, у меня под gcc-arm-none-eabi собирается с -hard.
Проект не мой, а сгенерённый визардом — галочки может нужной нету? Попробую makefile project собрать под hard. Может Yagarto просто не поддерживает hard-fpu.
0
Попробовал собрать ещё раз. Получил такое сообщение:

Building target: stm_01.elf
Invoking: Cross ARM C++ Linker
arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O2 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding  -g3 -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"stm_01.map" -o "stm_01.elf"  ./system/src/stm32f4-hal/stm32f4xx_hal.o ./system/src/stm32f4-hal/stm32f4xx_hal_cortex.o ./system/src/stm32f4-hal/stm32f4xx_hal_flash.o ./system/src/stm32f4-hal/stm32f4xx_hal_flash_ex.o ./system/src/stm32f4-hal/stm32f4xx_hal_flash_ramfunc.o ./system/src/stm32f4-hal/stm32f4xx_hal_gpio.o ./system/src/stm32f4-hal/stm32f4xx_hal_iwdg.o ./system/src/stm32f4-hal/stm32f4xx_hal_pcd_ex.o ./system/src/stm32f4-hal/stm32f4xx_hal_pwr.o ./system/src/stm32f4-hal/stm32f4xx_hal_pwr_ex.o ./system/src/stm32f4-hal/stm32f4xx_hal_rcc.o ./system/src/stm32f4-hal/stm32f4xx_hal_rcc_ex.o  ./system/src/newlib/_cxx.o ./system/src/newlib/_exit.o ./system/src/newlib/_sbrk.o ./system/src/newlib/_startup.o ./system/src/newlib/_syscalls.o ./system/src/newlib/_write.o ./system/src/newlib/assert.o  ./system/src/diag/Trace.o ./system/src/diag/trace_impl.o  ./system/src/cortexm/_initialize_hardware.o ./system/src/cortexm/_reset_hardware.o ./system/src/cortexm/exception_handlers.o  ./system/src/CMSIS/system_stm32f4xx.o ./system/src/CMSIS/vectors_stm32f4xx.o  ./src/BlinkLed.o ./src/Timer.o ./src/_initialize_hardware.o ./src/main.o   
c:/yagarto_20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/bin/ld.exe: error: stm_01.elf uses VFP register arguments, c:/yagarto_20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libg.a(lib_a-svfiprintf.o) does not
c:/yagarto_20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/bin/ld.exe: failed to merge target specific data of file c:/yagarto_20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libg.a(lib_a-svfiprintf.o)
...
collect2.exe: error: ld returned 1 exit status
make: *** [stm_01.elf] Ошибка 1

Получается что опция hard линкеру указана.
0
С -mhard-float, только судя по дизасму там нет вызовов, все инлайн.
0
Код совершенно лажовый в смысле объема — переписать все на asm (float point команды MAC VM**.F32 выполняются за 3 такта у Cortex-M4(см. стр.70)). И развернуть циклы. Если кто не знает что такое разворачивание цикла, это, например, следующий код:

int i;
float a = 0;
for (i = 0; i < 256; i++) {
    a += b*c;
}
превращаем в такой код:
int i;
float a = 0;
for (i = 0; i < 16; i++) {
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
}
т.е. в разы/десятки уменьшаем паразитное время на выполнение команд перехода и инкремента счетчика в цикле.
0
превращаем в такой код:
int i;
float a = 0;
//for (i = 0; i < 16; i++) { закоментили
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
    a += b*c;
//} закоментили
0
Тогда уже надо 256 строк с выражением a += b*c;
0
Добавил тест получше, получилось почти 2 такта на операцию.
0
Ну и… получил 80 MFLOPS, но самое интересное: а сколько надо было в итоге для реализации задачи? (Публика застыла в молчаливом ожидании)
0
Задача поставлена не так. Я оцениваю на сколько я могу рассчитывать, а не сколько надо. На более быстрые DSP переходить не хочется по разным причинам.

Пока насчитал, что смогу оценивать 8 переменных, из которых 3 (R, L, E) постоянные плавающие от температуры и нелинейности в магнитопроводе. Можно оставить только 5 переменных а постоянные оценивать заранее, при неподвижном роторе. Фильтр выдерживает уходы до 20%..40% судя по малочисленным тестам на модели. А можно добавить еще 2-3 переменных (дрейфы датчиков тока), но уже будет толстовато, и неизвестно получится ли все оценивать одновременно. Вариантов много, можно переключать фильтры во время работы, секунду оцениваем дрейфа, дальше снова R,L,E.
0
А какой rate оцифровки с ADC датчиков будет на входе этого фильтра? Это вопрос по поводу 80 MFLOPS.

P.S. Есть аналог такого(проектируемого) BLDC-контроллера уже at the Globe? И где его можно купить?
-1
Ну вот, почти голый фильтр на 6 переменных, достаточно оптимизированный, занимает 2756 тактов из 8400 доступных (~33%) при частоте 20кГц. Но этого мало, этих шести переменных хватит если заранее оценить сопротивление, индуктивности, и если нужно момент инерции. А измерения датчиков тока не должны содержать сильно дрейфующей постоянной составляющей. Ну и сопротивление обмотки не должно сильно изменяться во время работы, то есть надо брать значение для рабочего режима а не холодного двигателя.

Запас конечно еще есть, но с увеличением количества переменных сложность растет не линейно. А всего было бы хорошо оценивать 12 переменных.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.