В отличие от оптимизированных вручную подходов, представленных в замечательных ответах Вима и Майка, давайте также кратко рассмотрим, что даст нам полностью ванильная реализация C ++:
std::transform(addon, addon + count, canvas, canvas, std::plus());
Попробуйте здесь . Вы увидите, что даже без каких-либо реальных усилий с вашей стороны, компилятор уже может создавать векторизованный код, что весьма неплохо, учитывая, что он не может делать какие-либо предположения относительно выравнивания и размера ваших буферов, а также есть некоторые потенциальные проблемы с наложением ( из-за использования uint8_t
, который, к сожалению, заставляет компилятор предполагать, что указатель может иметь псевдоним для любого другого объекта). Также обратите внимание, что код в основном идентичен тому, что вы получите от реализации в стиле C (в зависимости от компилятора, версия C ++ содержит несколько инструкций больше или меньше инструкций)
void f(uint16_t* canvas, const uint8_t* addon, size_t count)
{
for (size_t i = 0; i < count; ++i)
canvas[i] += addon[i];
}
Однако универсальное решение C ++ работает с любой комбинацией различных типов контейнеров и типов элементов, если только можно добавить типы элементов. Таким образом, как также указывалось в других ответах, хотя, безусловно, можно получить чуть более эффективную реализацию от ручной оптимизации, можно проделать долгий путь, просто написав простой код C ++ (если все сделано правильно). Прежде чем прибегать к ручному написанию встроенных функций SSE, подумайте, что универсальное решение C ++ является более гибким, более простым в обслуживании и, особенно, более переносимым. Простым переключением переключателя целевой архитектуры вы можете заставить его генерировать код аналогичного качества не только для SSE, но и для AVX или даже для ARM с NEON и любыми другими наборами команд, которые могут вам понадобиться. Если вам нужно, чтобы ваш код был идеальным вплоть до последней инструкции для одного конкретного варианта использования на одном конкретном процессоре, тогда да, возможно, стоит использовать встроенную или даже встроенную сборку. Но в целом, я бы также предложил вместо этого сосредоточиться на написании своего кода на C ++ таким образом, чтобы компилятор мог и направлял сборку, которую вы хотите, а не генерировал сборку самостоятельно. Например, используя (нестандартный, но общедоступный) ограничивающий квалификатор и заимствуя хитрость, сообщая компилятору, что ваш count
всегда кратен 32
void f(std::uint16_t* __restrict__ canvas, const std::uint8_t* __restrict__ addon, std::size_t count)
{
assert(count % 32 == 0);
count = count & -32;
std::transform(addon, addon + count, canvas, canvas, std::plus());
}
, вы получите (-std=c++17 -DNDEBUG -O3 -mavx
)
f(unsigned short*, unsigned char const*, unsigned long):
and rdx, -32
je .LBB0_3
xor eax, eax
.LBB0_2: # =>This Inner Loop Header: Depth=1
vpmovzxbw xmm0, qword ptr [rsi + rax] # xmm0 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
vpmovzxbw xmm1, qword ptr [rsi + rax + 8] # xmm1 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
vpmovzxbw xmm2, qword ptr [rsi + rax + 16] # xmm2 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
vpmovzxbw xmm3, qword ptr [rsi + rax + 24] # xmm3 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
vpaddw xmm0, xmm0, xmmword ptr [rdi + 2*rax]
vpaddw xmm1, xmm1, xmmword ptr [rdi + 2*rax + 16]
vpaddw xmm2, xmm2, xmmword ptr [rdi + 2*rax + 32]
vpaddw xmm3, xmm3, xmmword ptr [rdi + 2*rax + 48]
vmovdqu xmmword ptr [rdi + 2*rax], xmm0
vmovdqu xmmword ptr [rdi + 2*rax + 16], xmm1
vmovdqu xmmword ptr [rdi + 2*rax + 32], xmm2
vmovdqu xmmword ptr [rdi + 2*rax + 48], xmm3
add rax, 32
cmp rdx, rax
jne .LBB0_2
.LBB0_3:
ret
, что действительно неплохо…
Было значение ключа обязательная платформа JavaScript под названием "Когерентный", который был вдохновлен Привязкой Какао Apple. Платформа была куплена Apple, но существует все еще старая копия по http://github.com/trek/coherentjs/tree/master.
Популярная платформа ActionScript MVC PureMVC была недавно портирована к JavaScript. У меня не было шанса испытать его все же, но я уверен, что это хорошо.
Я не назвал бы это микроплатформой, но этим верные взгляды интересный: веб-Платформа Капучино
Это - вероятно, излишество для того, в чем Вы нуждаетесь, но SproutCore является платформой MVC, и это больше не выглядит тяжелым, чем JavaScriptMVC или Соединение TrimPath.
К сожалению, ни один из них, кажется, не основан на принципе прогрессивного улучшения.
Действительно существует: http://www.javascriptmvc.com/
Я думаю, что Вы найдете это достаточным!
Если Ваши требования действительно просты, Вы могли бы записать, что Ваш собственный простой MVC как Alex Netkachov сделал.
Его примеры основаны на додзе (Примечание: они не работают на меня на его странице из-за отсутствия dojo.js файл), но Вы могли следовать за шаблоном в плоскости JavaScript.
Джамал самый легкий из тех, что я видел. Он также основан на jQuery (бонус). Не использовались.
JavaScriptMVC - отличное решение. Это все, что есть плагин, который позволяет вам выбирать только те функции, которые вам нужны. Начиная с версии 2.0, он основан на jQuery.
При постепенном улучшении вашего веб-сайта это остается на усмотрение пользователя, поскольку JMVC предоставляет только средний уровень для разработки - вам решать самостоятельно.
Однако JavaScriptMVC - это просто лучшая библиотека JavaScriptMVC общего назначения. благодаря мощным контроллерам, основанным на делегировании событий.
Делегирование событий позволяет избежать необходимости подключать обработчики событий и просто создавать правила для вашей страницы.
Наконец, JMVC - это гораздо больше, чем архитектура MVC. Он включает в себя все части цикла разработки:
Пожалуйста, также проверьте jquery-Claypool .
jquery-Claypool - это небольшая, быстрая, управляемая MVC-структура, построенная на jquery, на основе моего опыта работы с django, rails , Spring и т. д. Он очень легкий и работает как на клиенте, так и на сервере.
он обеспечивает структуру маршрутизации для чистого mvc, ведения журнала категорий, фильтров (aop), ленивого создания контроллеров, инверсии управления, соглашения -over-configuration и не более того.
он не делает того, что уже делает jquery, ощущается как jquery и работает как хороший фреймворк: просто.
Надеюсь, вы проверите