Настройка производительности сборки - PullRequest
9 голосов
/ 30 июня 2011

Я пишу компилятор (больше для удовольствия, чем все остальное), но я хочу попытаться сделать его максимально эффективным. Например, мне сказали, что в архитектуре Intel использование любого регистра, кроме EAX для выполнения математических вычислений, сопряжено с определенными затратами (предположительно, потому что оно переходит в EAX для выполнения математических операций). Вот по крайней мере один источник, который заявляет о возможности (http://www.swansontec.com/sregisters.html).

Я хотел бы проверить и измерить эти различия в характеристиках производительности. Таким образом, я написал эту программу на C ++:

#include "stdafx.h"
#include <intrin.h>
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    __int64 startval;
    __int64 stopval;
    unsigned int value; // Keep the value to keep from it being optomized out

    startval = __rdtsc(); // Get the CPU Tick Counter using assembly RDTSC opcode

    // Simple Math: a = (a << 3) + 0x0054E9
    _asm {
        mov ebx, 0x1E532 // Seed
        shl ebx, 3
        add ebx, 0x0054E9
        mov value, ebx
    }

    stopval = __rdtsc();
    __int64 val = (stopval - startval);
    cout << "Result: " << value << " -> " << val << endl;

    int i;
    cin >> i;

    return 0;
}

Я пытался поменять этот код eax и ebx, но у меня нет "стабильного" числа. Я хотел бы надеяться, что тест будет детерминированным (то же самое число каждый раз), потому что он настолько короткий, что вряд ли произойдет переключение контекста во время теста. В нынешнем виде статистической разницы нет, но число колеблется настолько сильно, что невозможно сделать такое определение. Даже если я беру большое количество образцов, их количество все равно невозможно изменить.

Я бы тоже хотел проверить xor eax, eax против mov eax, 0, но у меня такая же проблема.

Есть ли способ выполнить такие тесты производительности в Windows (или где-либо еще)? Когда я программировал Z80 для своего TI-Calc, у меня был инструмент, в котором я мог выбрать какую-то сборку, и он сообщал бы мне, сколько тактовых циклов для выполнения кода - разве это невозможно сделать с нашими новыми современными процессорами? 1016 *

РЕДАКТИРОВАТЬ: Есть много ответов, указывающих на запуск цикла миллион раз. Чтобы уточнить, это на самом деле делает все хуже. Процессор с большей вероятностью переключается из контекста, и тест становится обо всем, кроме того, что я тестирую.

Ответы [ 8 ]

10 голосов
/ 01 июля 2011

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

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

Практически единственной инструкцией сериализации, доступной в режиме пользователя, является CPUID.Это, однако, добавляет еще одну незначительную проблему: для CPUID задокументировано, что CPUID требует различного количества времени для выполнения - первая пара выполнений может быть медленнее, чем другие.

Таким образом, нормальная последовательность синхронизации дляВаш код будет выглядеть примерно так:

XOR EAX, EAX
CPUID
XOR EAX, EAX
CPUID
XOR EAX, EAX
CPUID            ; Intel says by the third execution, the timing will be stable.
RDTSC            ; read the clock
push eax         ; save the start time
push edx

    mov ebx, 0x1E532 // Seed // execute test sequence
    shl ebx, 3
    add ebx, 0x0054E9
    mov value, ebx

XOR EAX, EAX      ; serialize
CPUID   
rdtsc             ; get end time
pop ecx           ; get start time back
pop ebp
sub eax, ebp      ; find end-start
sbb edx, ecx

Мы начинаем приближаться, но есть последний момент, с которым трудно справиться с использованием встроенного кода на большинстве компиляторов: также могут быть некоторые эффекты от пересечениякэшировать строки, поэтому вы обычно хотите, чтобы ваш код был выровнен по 16-байтовой (абзацной) границе.Любой порядочный ассемблер поддержит это, но встроенная сборка в компиляторе обычно не будет.

Сказав все это, я думаю, вы тратите свое время.Как вы можете догадаться, я провел довольно много времени на этом уровне, и я совершенно уверен, что вы слышали, что это просто миф.В действительности все последние процессоры x86 используют набор так называемых «регистров переименования».Короче говоря, это означает, что имя, которое вы используете для регистра, на самом деле не имеет большого значения - процессор имеет гораздо больший набор регистров (например, около 40 для Intel), который он использует для реальных операций, поэтомуустановка значения в EBX против EAX мало влияет на регистр, который ЦП действительно собирается использовать внутри.Любой из них может быть сопоставлен с любым регистром переименования, в зависимости главным образом от того, какие регистры переименования оказываются свободными при запуске этой последовательности команд.

7 голосов
/ 01 июля 2011

Я бы посоветовал взглянуть на Agner Fog "Ресурсы для оптимизации программного обеспечения" - в частности, руководства по сборке и микроархитектуре (2 и 3), а также тестовый код, который включает в себя более сложный рамки для измерений с использованием счетчиков монитора производительности.

5 голосов
/ 01 июля 2011

Перейдите здесь и загрузите Справочное руководство по оптимизации архитектур.

Есть много мифов. Я думаю, что требование EAX является одним из них.

Также обратите внимание, что вы больше не можете говорить о том, «какая инструкция быстрее». На современном оборудовании нет соотношения 1 к 1 между инструкциями и временем выполнения. Некоторые инструкции предпочтительнее других не потому, что они «быстрее», а потому, что они нарушают зависимости между другими инструкциями.

5 голосов
/ 01 июля 2011

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

На современных процессорах x86 инструкции, использующие AX или EAX, не быстрее как таковые , но некоторые инструкции могут быть короче, чеминструкции с использованием других регистров.Это может просто сохранить байт в кэше команд!

4 голосов
/ 01 июля 2011

Вы получаете смешную дисперсию, потому что rdtsc не сериализует выполнение. В зависимости от недоступных деталей состояния выполнения, команды, которые вы пытаетесь сравнить, могут фактически выполняться полностью до или после интервала между rdtsc инструкциями! Вероятно, вы получите лучшие результаты, если вставите команду сериализации (например, cpuid) сразу после первого rdtsc и непосредственно перед вторым. См. эту техническую записку Intel (PDF) для подробностей.

4 голосов
/ 01 июля 2011

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

3 голосов
/ 01 июля 2011

Я думаю, что статья пытается сказать о регистре EAX, так как некоторые операции могут выполняться только с EAX, лучше использовать его с самого начала.Это было очень верно с 8086 (MUL приходит на ум), но 386 сделал ISA намного более ортогональным, поэтому в наши дни это гораздо менее верно.

3 голосов
/ 01 июля 2011

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

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

...