Структура в C, действительно ли они эффективны?

Я читаю некоторый код 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 }

и затем получите доступ к параметрам в функции.

6
задан pygabriel 12 March 2010 в 09:44
поделиться

8 ответов

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

Таким образом, в основном, когда вы передаете отдельные элементы, вызывающая сторону передает их в стек, и функция обращается к ним относительно стека. При передаче стркутуры вызывающая группа копирует элементы данных в блок памяти в стеке, а затем передает адрес этого в функцию, которая обращается к ним относительно этого.

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

На мой взгляд, использование структуры более понятно, и, по-видимому, нет существенных различий в скорости, поэтому выбирайте одну :)

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

5
ответ дан 8 December 2019 в 14:42
поделиться

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

0
ответ дан 8 December 2019 в 14:42
поделиться

Лучше всего профилировать и тестировать.

Но, во-первых, меньшие параметры будут скопированы в стек, когда вы передадите указатель на структуру. Кроме того, вызов функции может выглядеть более аккуратно.

0
ответ дан 8 December 2019 в 14:42
поделиться

Передача структуры или списка аргументов не должна иметь большого значения. Соглашение о вызовах требует, чтобы они передавались по значению и через стек (если функция не может быть объявлена ​​ static ).

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

0
ответ дан 8 December 2019 в 14:42
поделиться

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

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

5
ответ дан 8 December 2019 в 14:42
поделиться

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

Передача одного указателя на struct (4 байта) займет меньше инструкций, чем передача int, 3 двоек и указателя (32 байта), но если вам придется заполнить struct этими 32 байтами перед вызовом, то вы потеряете преимущество.

В любом случае, производительность всегда относительна, поэтому единственный способ определить, стоит ли это делать, - посмотреть, какой процент времени тратится на передачу аргументов. Для этого я просто запускаю программу и останавливаю ее случайным образом 10 или 20 раз. Если я не поймаю его на передаче этих аргументов более 10% времени, есть шанс, что есть более серьезные проблемы, которые можно исправить в первую очередь.

1
ответ дан 8 December 2019 в 14:42
поделиться

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

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

В любом случае, на этот вопрос нелегко ответить. Итак, как и в случае со всеми соображениями производительности: просто протестируйте и профилируйте!

5
ответ дан 8 December 2019 в 14:42
поделиться

Да, это так. Я бы поставил миллион баксов, будь у меня столько, что разница в производительности ничтожна.

0
ответ дан 8 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: