2013-11-17 4 views
2

Мне нужен лучший способ вычисления S-кривой, чем метод ниже. Я использую его, чтобы нарисовать S-Curve в методе drawRect, а также вычислить легкость/непринужденность объема музыкального файла для замирания.Векторные математические функции для S-кривой

Причина, по которой мне нужен улучшенный способ сделать это, состоит в том, что он вызывает примерно 100 раз в цикле для вычисления кривой и имеет высокую интенсивность процессора.

Я надеюсь, что может помочь одна или несколько векторных математических функций из ракурса ускорения, но я не уверен, с чего начать.

3 * position * (1 - position) * (1 - position) * firstControlPoint + 3 * 
position * position * (1 - position) * secondControlPoint + 
position * position * position * 1.0; 

Где firstControlPoint равно 0.0 и secondControlPoint равно 1.0.

ответ

1

Возможно, вас интересует эта статья по адресу Even Faster Bézier, но 100 расчетов этого не так много. Я выполнил тысячи таких вычислений за кадр на iPad первого поколения. Для такого крошечного набора you're unlikely to get much benefit from Accelerate (и Accelerate может быть намного медленнее, чем простой C для небольших наборов данных).

Есть несколько вещей, чтобы рассмотреть, хотя:

  • Если контрольные точки неизменны, вы должны быть в состоянии заранее рассчитать значения для всех позиций и наклеить их в таблице. Это значительно улучшит производительность. Если они меняются реже, чем вы рисуете, то по-прежнему стоит предварительно вычислять таблицу всякий раз, когда входы меняются. Кроме того, убедитесь, что вы не вычисляете эти значения чаще, чем вы на самом деле нуждаетесь в них (если входные значения могут быстро меняться, вам может потребоваться дождаться, когда входы будут установлены до пересчета чего-либо).

  • Если это устройство NEON (например, iPhone или iPad), intrinsics are almost never a win (это может измениться по мере улучшения Clang, но это было моим делом в 2012 году). Ручной код NEON может определенно стать победой, если вам действительно нужна производительность, но это головная боль для программирования, поэтому я сначала буду искать везде. Программирование сборок радикально отличается от программирования на C. Если бы вы могли просто отказаться от встроенного в определенный момент и сделать его быстрее, компилятор уже сделал бы это (и на самом деле это делает).

  • Если вы используете математику с плавающей запятой, и вам просто нужны, чтобы результаты были «почти точно правильными и идеальными для рисования и анимации», а не «точно верны и воспроизводимы в соответствии с правилами IEEE», вы должны включить быстрая математика. Самый простой способ сделать это - переключить оптимизацию компилятора с «Самый быстрый, самый маленький» на «Самые быстрые, агрессивные оптимизации». Трудно представить себе случай, когда это неправильная настройка для приложений для iOS, и это почти всегда правильная настройка для приложений Mac. Этот параметр также включает дополнительную векторию, которая может иметь большое значение в ваших циклах.

  • Вы должны обязательно посмотреть Оптимизируйте свой код с помощью LLVM от WWDC 2013. В нем рассказывается, как структурировать код, чтобы компилятор вам больше всего помог. Вы также можете посмотреть на Accelerate Framework из тех же видеороликов, но маловероятно, что Accelerate является правильным инструментом для этой проблемы.

  • Вместо того, чтобы рассчитывать это самостоятельно, рассмотрите возможность использования CAPropertyAnimation с пользовательской функцией синхронизации. Они могут использоваться для установки любого значения; а не только анимации слоев. Для рисования кривой рассмотрите возможность использования UIBezierPath, а не расчёта вручную.

Для примера некоторых это на практике, вы можете найти CurvyText пример с прошивкой раздвигает границы, чтобы быть полезным. Он вычисляет как точки Безье, так и их наклон для выполнения макета текста вдоль движущейся кривой.

1

Ваша S-кривая - кривая Безье, поэтому вы можете использовать De Casteljau's algorithm.

q0 = t * p0 + (1 - t) * p1 
q1 = t * p1 + (1 - t) * p2 
q2 = t * p2 + (1 - t) * p3 
r0 = t * q0 + (1 - t) * q1 
r1 = t * q1 + (1 - t) * q2 
s0 = t * r0 + (1 - t) * r1 

Тогда вы могли бы использовать SSE/AVX-встроенные функции для вычисления кратных кривых (2 -> 128 бит, 4 -> 256 бит) с одним потоком команд.

Смежные вопросы