Я читаю некоторый код C как этот:
double function( int lena,double xa,double ya, double za, double *acoefs, ...,
int lenb,double xb,double yb, double zb, double *bcoefs, ...,
same for c,
same for d )
Эта функция вызвана в гумусе кода, чем 100 000 раз, таким образом, это является критическим по отношению к производительности.
Я пытаюсь расширить этот код, но я хочу знать, эффективно ли это или не (и насколько это влияет на скорость) инкапсулировать все параметры в структуре как это
struct PGTO { int len; double x,y,z ; double *acoefs }
и затем получите доступ к параметрам в функции.
64-разрядный Visual C++ 2008, по-видимому, передает структуру, выделяя пространство для копии структуры в своем стеке и копируя в нее элементы данных, а затем передавая только адрес этой копии в функцию по значению.
Этот простой пример скомпилирован следующим образом -
struct data {
int a;
int b;
int c;
char d;
float f;
};
double f2(data d)
{
return d.a+d.b+d.c+d.d+d.f;
}
Компилируется в этот -
movsx eax, BYTE PTR [rcx+12]
add eax, DWORD PTR [rcx+8]
add eax, DWORD PTR [rcx+4]
add eax, DWORD PTR [rcx]
movd xmm0, eax
cvtdq2ps xmm0, xmm0
addss xmm0, DWORD PTR [rcx+16]
unpcklps xmm0, xmm0
cvtps2pd xmm0, xmm0
ret 0
Таким образом, в основном, когда вы передаете отдельные элементы, вызывающая сторону передает их в стек, и функция обращается к ним относительно стека. При передаче стркутуры вызывающая группа копирует элементы данных в блок памяти в стеке, а затем передает адрес этого в функцию, которая обращается к ним относительно этого.
Второй способ имеет еще пару инструкций по сборке, но это так, насколько я могу судить по моим тестам, нет никакой существенной разницы в эффективности между двумя методами вообще, кроме нескольких микросекунд.Во всех моих тестах компилятор хотел встраивать любые вызовы в любом случае, если только я не заставил его вызывать его через указатель, так что вполне возможно, что в вашей реальной программе вообще ничего не передается через стек.
На мой взгляд, использование структуры более понятно, и, по-видимому, нет существенных различий в скорости, поэтому выбирайте одну :)
Как всегда, если вы сомневаетесь в производительности, вам нужно профилировать свою точную настройку
Современные компиляторы, скорее всего, будут производить идентичный код в обоих случаях. Итак, если ваш компилятор не является современным, единственное (но важное) преимущество, которое вы получите от структур, - это улучшенная читаемость.
Лучше всего профилировать и тестировать.
Но, во-первых, меньшие параметры будут скопированы в стек, когда вы передадите указатель на структуру. Кроме того, вызов функции может выглядеть более аккуратно.
Передача структуры или списка аргументов не должна иметь большого значения. Соглашение о вызовах требует, чтобы они передавались по значению и через стек (если функция не может быть объявлена static
).
Вы можете провести рефакторинг кода, чтобы включить передачу по ссылке (передача указателя на структуру). Но это, вероятно, серьезный редизайн, который, вероятно, сделает ваш код более сложным и менее читаемым.
Прежде всего, использование структур кажется правильным способом именно в этом случае. Код будет намного легче читать и понимать, а также он станет менее загроможденным.
Передача указателя на структуру обычно дешевле, чем передача большого количества параметров.
Я бы предположил, что это зависит от того, как часто вам нужно заполнять struct.
Передача одного указателя на struct (4 байта) займет меньше инструкций, чем передача int, 3 двоек и указателя (32 байта), но если вам придется заполнить struct этими 32 байтами перед вызовом, то вы потеряете преимущество.
В любом случае, производительность всегда относительна, поэтому единственный способ определить, стоит ли это делать, - посмотреть, какой процент времени тратится на передачу аргументов. Для этого я просто запускаю программу и останавливаю ее случайным образом 10 или 20 раз. Если я не поймаю его на передаче этих аргументов более 10% времени, есть шанс, что есть более серьезные проблемы, которые можно исправить в первую очередь.
Ответ на этот вопрос во многом зависит от платформы и ее соглашений о вызовах. Это также зависит от того, может ли функция быть встроенной, и от других оптимизаций компилятора.
Я бы сказал, что на многих платформах версия структуры может быть более эффективной, поскольку меньше параметров, которые нужно скопировать в стек, если вы передаете указатель на структуру.
В любом случае, на этот вопрос нелегко ответить. Итак, как и в случае со всеми соображениями производительности: просто протестируйте и профилируйте!
Да, это так. Я бы поставил миллион баксов, будь у меня столько, что разница в производительности ничтожна.