Код медленнее в Linux по сравнению с Windows - PullRequest
4 голосов
/ 03 марта 2012

После изменения моего кода на C (написанного изначально для Windows и скомпилированного под VS 2008) я запустил его на Linux.К моему удивлению, это теперь по крайней мере в 10 раз медленнее, чем версия для Windows.

Используя инструменты Profiler Я выяснил, что следующая функция занимает большую часть времени, проводимого в приложении:

/* advance by n bits */

void Flush_Buffer(N)
int N;
{
 int Incnt;


 ld->Bfr <<= N;

Incnt = ld->Incnt -= N;

if (Incnt <= 24)
{
if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4))
{
do
{
if (ld->Rdptr >= ld->Rdmax)
      Next_Packet();
    ld->Bfr |= Get_Byte() << (24 - Incnt);
    Incnt += 8;
  }
  while (Incnt <= 24);
}
else if (ld->Rdptr < ld->Rdbfr+2044)
{
  do
  {
    ld->Bfr |= *ld->Rdptr++ << (24 - Incnt);
    Incnt += 8;
  }
  while (Incnt <= 24);
}
else
{
  do
  {
    if (ld->Rdptr >= ld->Rdbfr+2048)
      Fill_Buffer();
    ld->Bfr |= *ld->Rdptr++ << (24 - Incnt);
    Incnt += 8;
  }
  while (Incnt <= 24);
}
ld->Incnt = Incnt;
}

}

Эта функция занимала незначительное время в окнах.в Linux это занимает около 14 секунд.Что плохого я здесь совершил?

Здесь нет системных вызовов, поэтому этот раздел кода не должен зависеть от вызовов, специфичных для ОС, и, следовательно, должен выполняться в идентичное время.

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

Что я здесь не так совершил?Есть предположения?

Rgrds,

H

Ответы [ 2 ]

1 голос
/ 03 марта 2012

Это скорее примечание, чем ответ, но оно не совсем вписывается в комментарий, поэтому я надеюсь, что вы не будете относиться к нему против меня.

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

Например, предположим, что вы не уверены, должна ли какая-то структура данных быть std::set (дерево) или std::unordered_set (хеш-таблица).).Универсального ответа нет, поскольку он зависит от того, для чего вы его используете и какие данные вы обрабатываете.Вполне возможно, что вы не сможете знать правильный ответ, пока не укажете реальные, реальные данные, которые собираетесь использовать.В этом случае «профиль и решение» означает, что вы создаете две версии своей программы, запускаете их обе для ваших реальных данных и измеряете время выполнения.Вероятно, быстрее будет тот, который вам нужен.

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

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

0 голосов
/ 03 марта 2012

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

int count[100];

// Call this function at the end of program 
void PrintCounts() {
    int i;
    for(i=0; i<100; i++) printf("%d\n", count[i]);
}

void Flush_Buffer(int N) {
  int Incnt;

  ld->Bfr <<= N;

  Incnt = ld->Incnt -= N;

  if (Incnt <= 24) {
    count[0]++;
    if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4)) {
      count[1]++;
      do {
         count[2]++;
         ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...