2013-05-27 1 views
1

Я пытаюсь взять некоторые микрофункции кода Lua, но столкнулся с невероятно раздражающей проблемой: я не могу получить последовательные результаты.Непоследовательные результаты, пытающиеся выполнить microbenchmark

Пример: здесь мертвая простая программа Lua, которая должна время наивный функции Фибоначчи:

function pfibs(n) 
    if n ~= math.floor(n) then return 0 
    elseif n < 0 then return pfibs(n + 2) - pfibs(n + 1) 
    elseif n < 2 then return n 
    else return pfibs(n - 1) + pfibs(n - 2) 
    end 
end 
t = os.clock() 
pfibs(30) 
t = os.clock() - t 
print("time: "..t) 

Когда я пытаюсь запустить его несколько раз подряд, что-то подобное происходит:

$ lua fib.lua 
time: 1.265 
$ lua fib.lua 
time: 1.281 
$ lua fib.lua 
time: 1.343 
$ lua fib.lua 
time: 1.437 
$ lua fib.lua 
time: 1.562 
$ lua fib.lua 
time: 1.578 
$ lua fib.lua 
time: 1.64 
$ lua fib.lua 
time: 1.703 
$ lua fib.lua 
time: 1.75 
$ lua fib.lua 
time: 1.797 
$ lua fib.lua 
time: 1.796 
$ lua fib.lua 
time: 1.812 
$ lua fib.lua 
time: 1.89 

(это просто пример, сокращенный для краткости, но представляющий вид кривой замедления, который я вижу)

Времена, начинающиеся примерно на 1,1 секунды, заканчиваются хорошо ove две секунды. Все, что я делаю, сидит здесь, нажимая кнопку «Ввод». То же самое происходит, если я завершу тест при вызове time вместо использования часов Lua, или если я сделаю это несколько раз, чтобы взять еще пару секунд; он, похоже, замедляется пропорционально. Если я оставлю это на некоторое время, иногда времена возвращаются. Иногда нет (возможно, потому, что я не знаю, как долго его оставить).

Это на Windows + MSYS. Попытка этого на Ubuntu (тот же самый компьютер) приводит к другому шаблону, но все еще дико непоследовательны и непригодны к результату (например, тест займет 2 секунды, затем 3,5 секунды, затем 4 секунды, затем 2,5 секунды ...). Диспетчер задач/верхний уровень указывает на то, что в обоих случаях процессор игнорируется. Переключение скорости процессора отключено.

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


Что я на самом деле пытаюсь сделать:

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


Edit: Добавление C тега, так как то же самое происходит в программах C с использованием обычных утилит синхронизации C, а также, например:

#include <time.h> 
#include <stdio.h> 

int fib(int n) { 
    return n > 2 ? fib(n - 1) + fib(n - 2) : n; 
} 

int main(void) { 
    clock_t t1, t2; const int ITNS = 30; 
    for (int i = 0; i < ITNS; i ++) { 
     t1 = clock(); 
     fib(38); 
     t2 = clock(); 
     printf("time: %d\n", (int)((t2 - t1)/(CLOCKS_PER_SEC/1000))); 
    } 
    return 0; 
} 

... печатает следующее:

time: 687 
time: 688 
time: 687 
time: 688 
time: 671 
time: 688 
time: 687 
time: 688 
time: 672 
time: 687 
time: 688 
time: 687 
time: 672 
time: 688 
time: 687 
time: 688 
time: 672 
time: 796 
time: 766 
time: 719 
time: 969 
time: 1000 
time: 1015 
time: 1000 
time: 1016 
time: 1000 
time: 1000 
time: 1015 
time: 1000 
time: 1000 

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

+0

Я думаю, что нет ничего общего с ОС, поскольку все вычисления происходят в пользовательском пространстве. – Naruil

+0

Я тестировал свои c-программы на своих серверах Intel и AMD и всегда стабилен. Можете ли вы разместить здесь спецификации вашего компьютера/ОС? – Naruil

+0

Одна из вещей, которую вы должны сделать, - это изменить настройку регулятора по требованию или по мощности на производительность. Также см. ['Rulor.sh'] (https://github.com/weidai11/cryptopp/blob/master/TestScripts/governor.sh) из проекта Crypto ++, который заимствовал его у Энди Полякова из проекта OpenSSL. – jww

ответ

3

Ваша программа выглядит очень стабильным на моей машине с Xeon E7-4850

time: 0.97 
time: 0.98 
time: 1 
time: 0.98 
time: 1.01 
time: 1 
time: 0.98 
time: 0.98 
time: 1.02 
time: 0.98 

Однако, я предлагаю вам проверить, если процессор частоты масштабирования или что-то вроде Turbo Boost включен когда вы запускаете тесты. Ранее мы сталкивались с подобными проблемами, но когда мы отключили частоту масштабирования, эталонность становится стабильной. В Linux вы можете использовать cpufrequtils, чтобы отключить его.

Кроме того, если вы используете машину AMD, я предлагаю просто переключиться на интеллектуальную, поскольку даже если частота процессора исправлена, производительность программ lua по-прежнему нестабильна для нашего Opteron 8431. Таким образом, эта проблема может зависеть от а не Lua-интерпретатор.

Edit:

Я думаю, что лучше читать и печатать текущую частоту процессора (с/Proc/CPUInfo или/Dev/CPU/#/MSR) после каждой итерации, чтобы убедиться, что частота стабильна.

Ваш результат с программой C имеет две четкие стабильные ступени. Похоже, что что-то произошло после того, как run19 и частота процессора снизились.

enter image description here

+0

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

0

rdtsc основанное измерение времени не зависит от изменений частоты процессора.
Вы можете попробовать свои стандарты в LuaJIT с переопределена os.clock функции следующим образом
(только настроить ваш CPU_speed константа для правдоподобных значений времени, которое будет отображаться):

-- New os.clock() implementation based on rdtsc instruction, LuaJIT required 
do 
    local CPU_speed = 3.0 -- Your CPU speed in GHz 
    local rdtsc = require'ffi'.cast(
     '__cdecl uint64_t(*)()', 
     '\x0F\x31\xC3' -- rdtsc, ret 
    )     -- This trick may not work on modern 64-bit OS 
    local rdtsc0 = rdtsc() 
    os.clock = function() 
     return tonumber(rdtsc() - rdtsc0)/(CPU_speed * 10^9) 
    end 
end 
+1

Пробовал C, а не LuaJIT, но, к сожалению, 'rdtsc', похоже, показывает тот же шаблон. Где бы ни была проблема, это где-то в другом месте. – Leushenko

+0

Проблема, похоже, на стороне вашей ОС. Осмотрите использование ЦП (если у вас есть 2 или более ядра ЦП) и использование памяти во время тестирования. Возможно, предыдущий процесс не был прекращен до начала нового процесса? –

+0

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

0

Не уверен, насколько это технически «solution», но:

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

Используя CPU-Z, я заметил, что температура также показалась всплескам одновременно с внезапным замедлением. Он только прыгал с 60 до 72 градусов (на a CPU that supposedly goes up to 100 degrees), но корреляция существовала. Когда частота заблокирована до минимума, этого больше не происходит, и не происходит замедление.

Я думаю, что эта проблема может быть поставлена ​​на «мой компьютер устарел и ненадежен», и вопрос должен быть закрыт, потому что это, по-видимому, вообще не проблема общего программирования.

Спасибо за вашу помощь.

+0

Нет, такое поведение ожидается. CPU будет автоматически уменьшаться при высокой температуре независимо от того, отключено ли вы масштабирование частоты. Иногда вы можете даже настроить порог в конфигурациях BIOS. 100 градусов - это самая высокая допустимая температура вашего процессора, и в этом случае он будет автоматически отключен. Я предлагаю вам очистить пыль внутри вашей машины и повторить попытку^_ ^ – Naruil

Смежные вопросы