Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Опытный кот
Аватара пользователя
Сообщения: 791
Зарегистрирован: Вт июн 17, 2014 00:34:26

Сообщение baghear »

[uquote="arkhnchul",url="/forum/viewtopic.php?p=3265434#p3265434"]телепатирую: вы где-то присваиваете переменной с типом enum значение какого-то из int-ов, или наоборот.[/uquote]
Для чего вы вангуете?
Там это явно написано, меня интересует как убрать warning. Как дать понять компилятору, что делаю это осознано.
Реклама
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

Сообщение arkhnchul »

ну первый очевидный и правильный вариант - не делать так) если все-таки это нужно, то можно явно привести типы в нужных местах.
Реклама
Мудрый кот
Сообщения: 1840
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="baghear",url="/forum/viewtopic.php?p=3265557#p3265557"][uquote="arkhnchul",url="/forum/viewtopic.php?p=3265434#p3265434"]телепатирую: вы где-то присваиваете переменной с типом enum значение какого-то из int-ов, или наоборот.[/uquote]
Там это явно написано, меня интересует как убрать warning. Как дать понять компилятору, что делаю это осознано.[/uquote]
Естественно - явно привести типы. А вы чего ожидали?
Друг Кота
Аватара пользователя
Сообщения: 25862
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Apparatchik",url="/forum/viewtopic.php?p=3265438#p3265438"]Нужно циклически сдвинуть массив типа int16_t вправо, как думаете какая из[/uquote]
Стесняюсь спросить, а зачем нужно двигать массив? Вообще то принято двигать указателями....
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

[uquote="КРАМ",url="/forum/viewtopic.php?p=3265666#p3265666"]Стесняюсь спросить, а зачем нужно двигать массив? Вообще то принято двигать указателями....[/uquote]
В конкретном случае нужно скомпенсировать отставние тока от напряжения при измерении трансформатором тока. Тоесть имеется выборка АЦП измерений за период и нужно её сдвинуть циклически на некоторое значение как можно быстрее, даже в ущерб памяти, главное скорость (ассемблер не предлагать). Эксперементально выяснено что второй вариант работает лучше, но может есть более быстрые варианты.
«И всё-таки она вертится!»
Реклама
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

Сообщение arkhnchul »

непонятно, зачем сами значения туда-сюда перекладывать. Организуйте кольцевую структуру и двигайте указатель на условное начало
Реклама
Друг Кота
Аватара пользователя
Сообщения: 25862
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Apparatchik",url="/forum/viewtopic.php?p=3265744#p3265744"]В конкретном случае нужно скомпенсировать отставние тока от напряжения при измерении трансформатором тока.[/uquote]
Вам выше подтвердили мою сентенцию на этот счет.
Однако, а зачем вообще Вам нужно это фазирование тока и напряжения? Что Вы собираетесь посчитать?
У меня опять смутные подозрения на Ваш счет... :tea:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

АЦП складывает выборку в массив за период, пока складывает надо обработать предыдущую. При активной нагрузке ток немного сдвинут относительно напряжения (а не должен) из-за измерительного трансформатора, это видно как на графике так и при вычислении коофициента мощности (PF). Для компенсации индуктивности трансформатора нужно ток сдвинуть относительно напряжения. В общем зачем эти подробности? Я же сказал что уже работает и просто спросил может можно сдвинуть как то быстрее. Нет так нет.
«И всё-таки она вертится!»
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Apparatchik писал(а):Эксперементально выяснено что второй вариант работает лучше, но может есть более быстрые варианты.
то есть я угадал, предположив, что libc содержит оптимальную memcpy. тогда снова предположу, что еще быстрее сдвинуть можно при помощи DMA...

Добавлено after 1 minute 27 seconds:
Но вообще гоовря, вам дают верные советы: вместо сдвига буфера целиком можно обрабатывать, грубо говоря, i-ую выборку напряжения и (i+4)-ую выборку тока, вот и будет сдвиг...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

[uquote="ARV",url="/forum/viewtopic.php?p=3265903#p3265903"]то есть я угадал, предположив, что libc содержит оптимальную memcpy. тогда снова предположу, что еще быстрее сдвинуть можно при помощи DMA...[/uquote]
Видимо да, но она всеже копирует побайтно, для типа int16_t я размер умножил на 2.
[uquote="ARV",url="/forum/viewtopic.php?p=3265903#p3265903"]Но вообще гоовря, вам дают верные советы: вместо сдвига буфера целиком можно обрабатывать, грубо говоря, i-ую выборку напряжения и (i+4)-ую выборку тока, вот и будет сдвиг...[/uquote]
Выборки две, они набираются паралельно, на 400 элементов, но одну нужно сдвинуть относительно другой, обычно на 5-6 элементов, но может менятся. Сдвинуть надо именно циклично, тоесть задние элемеенты должны оказатся с переди, это важно для следуйщих расчетов.
«И всё-таки она вертится!»
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Apparatchik писал(а):Выборки две, они набираются паралельно, на 400 элементов, но одну нужно сдвинуть относительно другой, обычно на 5-6 элементов, но может менятся. Сдвинуть надо именно циклично, тоесть задние элемеенты должны оказатся с переди, это важно для следуйщих расчетов.
да все понятно уже. все получается абсолютно без сдвигов

Код: Выделить всё

int16_t buf_U[400];
int16_t buf_I[400];

#define SDVIG    5

//обрабатываете свои буферы С УЧЕТОМ СДВИГА как-то так
uint16_t index_I=SDVIG;
int32_t sum;
for(int i=0; i<400; i++){
   sum += buf_U[i] * buf_I[index_I];
   if(++index_I >= 400) index_I = 0;
} 
и не надо весь массив двигать, достаточно считывать из него со смещением.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

Я Вашу мысль понял, но там есче нужно после сдвига сделать вот это (только не спрашивайте зачем):

Код: Выделить всё

	// пишем в первую половину массива разницу между первой и второй половиной,
	for (i = max_index / 2, j = i; i < max_index; i++) {
		current[i - j] -= current[i];
	}
	// во вторую половину пишем первую с противоположным знаком
	for (i = max_index / 2, j = i; i < max_index; i++) {
		current[i] = current[i - j] * (-1);
	}
И только потом массив тока и напряжения используются в расчетах вместе по элементно. Массив напряжения подготавливается отдельно, но там все проще и быстро.
«И всё-таки она вертится!»
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Мудрый кот
Сообщения: 1840
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="Apparatchik",url="/forum/viewtopic.php?p=3265930#p3265930"]Я Вашу мысль понял, но там есче нужно после сдвига сделать вот это[/uquote]
Разбейте массив current[SIZE] на две части current[2][SIZE/2], заведите доп. переменную индекса i1 и
после каждой итерации меняйте части массива местами: i1 ^= 1;
Тогда не надо будет ничего "двигать".

Добавлено after 4 minutes 1 second:
[uquote="ARV",url="/forum/viewtopic.php?p=3265921#p3265921"]if(++index_I >= 400) index_I = 0;[/uquote]
Иногда лучше сделать memcpy() чем в цикле на каждой итерации делать такое. Лучше по скорости работы.
Автору нужна скорость, а такое управление индексом добавит кучу лишних тактов в цикл. Много больше чем memcpy() на больших выровненных массивах.
Для скорости будет лучше сделать memcpy().
А если ещё и 16-битные значения в массивах всё-таки знаковые или беззнаковые, но в диапазоне 0...32767 и работает на Cortex-M4 или выше, то круче будет:

Код: Выделить всё

int32_t sum = 0;
uint32_t *p1 = &buf_U[0], *p2 = buf_I[SDVIG];
int i = 400 / 2;
do sum = __SMLAD(*p1++, *p2++, sum);
while (--i);
И подровнять расположение массивов на границу 32 бит.
Да и если, как пишет автор, памяти не жалко, то кольцевые массивы можно кратно увеличить уменьшив также кратно количество вызовов memcpy().
Ну или организовать данные в массивах как я выше описал.
Последний раз редактировалось jcxz Пт дек 22, 2017 13:24:09, всего редактировалось 2 раза.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

jcxz писал(а):такое управление индексом добавит кучу лишних тактов в цикл. Много больше чем memcpy() на больших выровненных массивах.
только вы забываете, что у автора обработка в цикле ПОСЛЕ memcpy, т.е. все такты копирования пойдут плюсом к обработке. а управление индексом добавить по 2-3 такта на итерацию ПОЛЕЗНОГО цикла. так что это еще большой вопрос, что окажется быстрее по совокупности
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Мудрый кот
Сообщения: 1840
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ARV",url="/forum/viewtopic.php?p=3266075#p3266075"]
jcxz писал(а):такое управление индексом добавит кучу лишних тактов в цикл. Много больше чем memcpy() на больших выровненных массивах.
только вы забываете, что у автора обработка в цикле ПОСЛЕ memcpy, т.е. все такты копирования пойдут плюсом к обработке. а управление индексом добавить по 2-3 такта на итерацию ПОЛЕЗНОГО цикла. так что это еще большой вопрос, что окажется быстрее по совокупности[/uquote]
А вы компилировать пробовали, то что предложили? Где там 2-3 такта? Там все 20 будет на итерацию.
Так как используется дополнительные манипуляции с индексом, то компилятор не сможет адресацию через индексы заменить на адресацию через указатели, а это добавит кучу команд вычисления адресов операций чтения и записи в каждой итерации не считая самой
if(++index_I >= 400) index_I = 0;
которая уже выльется как минимум в 4 команды. И это хорошо если компилятор использует операцию условного выполнения ITxxx, а если нет то поставит условный переход - это будет ещё хуже.
Без этого компилятор заменит все ваши индексные операции с массивами на операции с указателями и на каждой итерации для чтения будет использовать только по две команды LDRH Rx, [Rx], #2.
Если имеется if(++index_I >= 400) index_I = 0; то он не сможет использовать указатели вычисленные перед началом цикла.
Кроме того данные у автора 16-битные, а memcpy() внутри оптимизирована и на больших массивах, выровненных на границу 32бит, будет копировать по 8 шт. 32-битных слов за итерацию, т.е. - будет тратить всего ~ 2 такта на копирование каждой пары значений.
А если ещё как я писал, кратно увеличить размеры массивов, то во столько же крат можно уменьшить количество вызовов memcpy().
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

jcxz писал(а):А вы компилировать пробовали, то что предложили?
нет, конечно.
jcxz писал(а):Кроме того данные у автора 16-битные, а memcpy() внутри оптимизирована и на больших массивах, выровненных на границу 32бит, будет копировать по 8 шт. 32-битных слов за итерацию, т.е. - будет тратить всего ~ 2 такта на копирование каждой пары значений.
собственно, с этого я и начал, так что не надо мне об этом рассказывать.

а все наши с вами рассуждения могут ничего не стоить, если компилятор хорошо оптимизирует.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 908
Зарегистрирован: Вс май 23, 2010 13:55:42
Откуда: Украина, Александрия

Сообщение Apparatchik »

[uquote="jcxz",url="/forum/viewtopic.php?p=3266089#p3266089"]А если ещё как я писал, кратно увеличить размеры массивов, то во столько же крат можно уменьшить количество вызовов memcpy().[/uquote]
Этого сделать нельзя так, как в зависимости от частоты количество измерений на период разное и в идиале составляет 400шт, но постоянно плавает.
«И всё-таки она вертится!»
Мудрый кот
Сообщения: 1840
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="ARV",url="/forum/viewtopic.php?p=3266096#p3266096"]а все наши с вами рассуждения могут ничего не стоить, если компилятор хорошо оптимизирует.[/uquote]
По-любому лучшая оптимизация индексных обращений к массивам - замена и на обращения через указатели, вычисленные перед циклом.
А в теле цикла - работа с этими указателями командами с автоинкрементом.
Но если есть модификация индексов внутри цикла, то заменить на указатели компилятор не сможет. А значит на каждой итерации будет заново считать исполнительные адреса для каждого операнда.
Вот во что компилируется приведённый мной код:

Код: Выделить всё

  u32 *p1 = &d.sh.bp[0], sum = 0;
  enum {SDVIG = 100};
  int i = 400 / 2;
  do {
    sum = __SMLAD(p1[0], p1[SDVIG], sum);
    p1++;
  } while (--i);
Быстрее почти некуда:

Код: Выделить всё

MOVS     R0,#+200
??DtePwm_0:
LDR      R3,[R2, #+400]
LDR      R6,[R2], #+4
SUBS     R0,R0,#+1
SMLAD    R1,R6,R3,R1
BNE.N    ??DtePwm_0
Всего 6 тактов на каждые 2 пары операндов (не считая условного перехода).

Добавлено after 4 minutes 9 seconds:
[uquote="Apparatchik",url="/forum/viewtopic.php?p=3266102#p3266102"]Этого сделать нельзя так, как в зависимости от частоты количество измерений на период разное и в идиале составляет 400шт, но постоянно плавает.[/uquote]
Ну и что?
Создаёте массив скажем примерно в 10 раз больше = 4000 значений. А это значит, что если в кольцевой буфер размером 400 значений каждый раз добавлять по примерно 400 новых значений, то значит примерно на одно добавление будет примерно одно пересечение границы. А если размер == 4000 значений, то значит пересечение будет примерно на каждое 10-е добавление.
А делать memcpy() нужно только при пересечении границы массива.
Так что без разницы - что фиксированное кол-во добавлять, что переменное.
Друг Кота
Аватара пользователя
Сообщения: 25862
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="Apparatchik",url="/forum/viewtopic.php?p=3265900#p3265900"]В общем зачем эти подробности? Я же сказал что уже работает и просто спросил может можно сдвинуть как то быстрее. Нет так нет.[/uquote]
Ну хотя бы затем, что порой не слишком, ээээ, оптимальный метод измерений дает раздутые никчемные расчеты. А порой и избыточные исходные данные.
Ответить

Вернуться в «Разные вопросы по МК»