Предположим, у меня есть два целых массива a
и b
с 10 int
s за массив. Есть ли способ добавить содержимое b[i]
в a[i]
с использованием трюка «memset» или «memcopy»? Я просто ищу что-то быстрее, чем очевидное для цикла w/a[i] += b[i]
и т. Д.Глупый вопрос о массивах в c и/или C++
ответ
"Глупый" - Я думаю, что это отличный вопрос!
Вы говорите, что «добавление» не «копировать» и я предполагаю, что x86:
void addintvector (int *dstp, const int *srcp, int nints)
{
int *endp;
endp=dst+nints;
nints=srcp-dstp; // reuse nints
while (dstp!=endp)
{
*dstp+=*(dstp+nints); // makes use of the [base+index*4] x86 addressing
dstp+=1; // some prefer ++dstp but I don't when it comes to pointers
}
}
Петля должна перевести в
add_label:
mov eax,[ebx+esi*4]
add [ebx],eax
add ebx,4
cmp ebx,edx
jne add_label
Это пять команд в цикле: он не получит гораздо быстрее!
Это также легко клонировать для вычитания, деления и умножения вариантов.
Некоторые говорят об использовании графического процессора, но для этого требуется, чтобы: 1. графический процессор взаимодействовал с приложениями и 2. ваш массив был достаточно большим, чтобы преодолеть связанные с этим накладные расходы.
Чтобы преодолеть накладные расходы на вызов/возврат, вы можете поэкспериментировать с объявлением его встроенным.
Редактировать
Я только что прочитал комментарий «так как это для игры на мобильном устройстве», и я предполагаю, что это не платформа x86 и поэтому, вероятно, не имеет рег + рег * шкала режима адресации.Если это так, код должен быть написан
void addintvector (int *dstp, const int *srcp, int nints)
{
int *endp;
endp=dst+nints;
while (dstp!=endp)
{
*dstp+=*srcp;
srcp+=1;
dstp+=1;
}
}
Не зная, какую архитектуру вы ориентируетесь, но предполагая RISC я думаю код будет восемь инструкций долго вместо этого (в «неоптимизированном» psuedocode):
add_label:
mov tempreg1,[srcreg]
mov tempreg2,[dstreg]
add tempreg2,tempreg1
mov [dstreg],tempreg2
add srcreg,4
add dstreg,4
cmp dstreg,endreg
jne add_label
Позвольте мне сказать, что это, по крайней мере, для x86, ужасная идея. Gcc будет векторизовать простой for-loop, но в общем случае не сможет этого сделать при перезаписи для использования указателей. – EmeryBerger
@EmeryBerger: Ваш комментарий неясен, так как я не могу понять, является ли это x86 вообще или комбинацией x86 и gcc. Я предполагаю, что вы имеете в виду, что в целом генерируемый код gcc будет выполняться в (эквиваленте) менее пяти инструкций для каждого добавления. Также неясно, является ли это вашим личным мнением или если это абсолютная истина. Для последнего вы должны предоставить соответствующие ссылки. –
попытайтесь скомпилировать простой for-loop с -O3 для любого процессора с SSE. Посмотрите на код сборки. Вы обнаружите, что он заменил операции с добавлением и памятью широкими векторными инструкциями, которые в целом намного быстрее. См. Http://gcc.gnu.org/projects/tree-ssa/vectorization.html. – EmeryBerger
Не то, чтобы я знал.
Является ли очевидная петля настолько медленной, что вам действительно нужно что-то «быстрее»? Как вы могли улучшить его?
Почему вы сомневаетесь в его причинах для того, чтобы задать вопрос? -1 –
Простой цикл добавления обычно будет достаточно быстрым, поскольку компилятор будет его векторизовать: http://gcc.gnu.org/projects/tree-ssa/vectorization.html, выводя параллельные инструкции, которые будут работать на четырех элементах массивов одновременно.
Если инструкции SIMD в вашем процессоре не достаточно быстры, вы можете в векторном формате увеличить масштаб с помощью OpenCL на вашем графическом процессоре. –
Возможно, стоит рассмотреть OpenCL. Если у вас много векторных или матричных задач, давайте не будем решать GPU. Взгляните на образец с суммой векторов https://www.wiki.ed.ac.uk/display/ecdfwiki/OpenCL+quick+start
Это должно быть достаточно большим, чтобы иметь значение. Накладные расходы связаны с отправкой данных по шине на GPU. Я сомневаюсь, что это победа на 10 очков. 1000 или более, может быть. –
Согласен. Мой подход имеет смысл, например, если у одного есть много пар векторов, чтобы добавить одно и то же время. Тогда можно объединить 10-элементные векторы в большой и отправить его на GPU. –
Если вы хотите использовать «чистый» C, в C99 есть переменные макросы. Используйте P99 для разматывания:
#include "p99_for.h"
#define ADDIT(Y, X, I) X[I] += Y[I]
#define ADD_MORE(Y, X, N) P99_FOR(Y, N, P00_SEP, ADDIT, P99_DUPL(N, X))
линия как
ADD_MORE(A, B, 3);
Затем расширяется
B[0] += A[0]; B[1] += A[1]; B[2] += A[2];
std::valarray
кажется хорошим выбором.
#include <valarray>
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
std::valarray<int> a(3, 10);
std::valarray<int> b(4, 10);
std::valarray<int> result = a + b;
std::copy(&result[0], &result[0] + result.size(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
a
и b
массивы с десятью элементами, 3 и 4 соответственно. Добавление двух valarray
s выполняет элементное добавление. Существует множество других арифметических операций, определенных для valarray
с.
Вам нужно будет проверить, выполняется ли это быстрее, чем явный цикл. Поскольку valarrays
предназначены для таких операций, реализация может быть каким-то образом оптимизирована.
- 1. Глупый C++ ссылка вопрос
- 2. Глупый C# массив вопрос
- 3. Глупый вопрос наследования в C#
- 4. о массивах в C++
- 5. Возможно глупый вопрос о строках и ссылки в C#
- 6. вопрос о массивах
- 7. глупый вопрос о строках в AS3
- 8. глупый «важный» вопрос о php $ _SESSION array
- 9. Вопросы о указателях и массивах в C
- 10. О указателях и массивах в C++
- 11. Очень простой вопрос о массивах
- 12. Вопрос о таймерах C++
- 13. Вопрос о сериализации C#
- 14. C# Вопрос о событиях
- 15. Вопрос о C#
- 16. Вопрос о компиляторе C#?
- 17. Вопрос о C# ковариации
- 18. вопрос о C# asp.net
- 19. Вопрос о стандарте C++
- 20. Вопрос о объективе-C?
- 21. Вопрос о C построить
- 22. вопрос о C++
- 23. C++ - Вопрос о ЬурейиХ
- 24. Вопрос о C++ Templates
- 25. Вопрос о C-петлях
- 26. PHP Jabber Глупый вопрос
- 27. Глупый вопрос с UTF8
- 28. Подклассификация UICollectionViewCell, глупый вопрос
- 29. Глупый вопрос, если блок
- 30. вопрос о C++ шаблон
Нужно ли переносить его? – EmeryBerger
Кроме того, посмотрели ли вы на код сборки? Я предполагаю, что вы профилировали свой код и решили, что это имеет значение. Если нет, придерживайтесь ясности. Если это так, посмотрите на сборку - на высоких уровнях оптимизации вы можете быть удивлены тем, насколько хорош результирующий код. – EmeryBerger
Существующий код прилично быстр ... однако, поскольку он предназначен для игры на мобильном устройстве, я хочу, чтобы это было так быстро, как я могу это сделать. Также мне просто любопытно в целом. Спасибо за ответы :-) – MrDatabase