Структурировать в C, они эффективны? - PullRequest
6 голосов
/ 12 марта 2010

Я читаю какой-то код на С так:

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 }

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

Ответы [ 8 ]

5 голосов
/ 12 марта 2010

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

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

5 голосов
/ 12 марта 2010

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

Этот простой пример скомпилирован следующим образом -

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

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

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

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

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

5 голосов
/ 12 марта 2010

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

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

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

1 голос
/ 12 марта 2010

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

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

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

0 голосов
/ 12 марта 2010

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

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

0 голосов
/ 12 марта 2010

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

0 голосов
/ 12 марта 2010

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

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

0 голосов
/ 12 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...