Решение: Очевидно, виновником было использование floor()
, производительность которого оказалась зависимой от ОС в glibc.
Это следующий вопрос к предыдущему: Такая же программа быстрее в Linux, чем Windows, - почему?
У меня есть небольшая программа на С++, которая при компиляции с nuwen gcc 4.6.1 работает быстрее на Wine, чем Windows XP (на том же компьютере). Вопрос: почему это происходит?
Тайм-ауты составляют ~ 15,8 и 25,9 секунды, для Wine и Windows соответственно. Обратите внимание, что я говорю об одном и том же исполняемом файле, а не только о той же программе на С++.
Исходный код находится в конце сообщения. Скомпилированный исполняемый файл здесь (если вы доверяете мне достаточно).
Эта конкретная программа не делает ничего полезного, это всего лишь минимальный пример, сложенный с большей программы, которую я имею. См. этот другой вопрос для более точного бенчмаркинга исходной программы (важно!!), и наиболее распространенные возможности исключены (например, другие программы, запугивающие CPU на Windows, штраф запуска процесса, разницу в системных вызовах, таких как распределение памяти). Также обратите внимание, что в то время как здесь я использовал rand()
для простоты, в оригинале я использовал свой собственный RNG, который, как я знаю, не выделяет кучу.
Причина, по которой я открыла новый вопрос по этой теме, заключается в том, что теперь я могу опубликовать фактический упрощенный пример кода для воспроизведения этого явления.
Код:
#include <cstdlib>
#include <cmath>
int irand(int top) {
return int(std::floor((std::rand() / (RAND_MAX + 1.0)) * top));
}
template<typename T>
class Vector {
T *vec;
const int sz;
public:
Vector(int n) : sz(n) {
vec = new T[sz];
}
~Vector() {
delete [] vec;
}
int size() const { return sz; }
const T & operator [] (int i) const { return vec[i]; }
T & operator [] (int i) { return vec[i]; }
};
int main() {
const int tmax = 20000; // increase this to make it run longer
const int m = 10000;
Vector<int> vec(150);
for (int i=0; i < vec.size(); ++i)
vec[i] = 0;
// main loop
for (int t=0; t < tmax; ++t)
for (int j=0; j < m; ++j) {
int s = irand(100) + 1;
vec[s] += 1;
}
return 0;
}
UPDATE
Кажется, что если я заменил irand()
на что-то детерминированное, например
int irand(int top) {
static int c = 0;
return (c++) % top;
}
тогда разница во времени исчезает. Я хотел бы отметить, что в моей оригинальной программе я использовал другой RNG, а не систему rand()
. Я сейчас врываюсь в источник этого.
ОБНОВЛЕНИЕ 2
Теперь я заменил функцию irand()
эквивалентом того, что у меня было в исходной программе. Он немного длинный (алгоритм от Numerical Recipes), но дело в том, чтобы показать, что никакие системные библиотеки не называются эксплицитно (кроме возможно, через floor()
). Однако разница во времени все еще существует!
Возможно, может быть виноват floor()
? Или компилятор генерирует вызовы на что-то еще?
class ran1 {
static const int table_len = 32;
static const int int_max = (1u << 31) - 1;
int idum;
int next;
int *shuffle_table;
void propagate() {
const int int_quo = 1277731;
int k = idum/int_quo;
idum = 16807*(idum - k*int_quo) - 2836*k;
if (idum < 0)
idum += int_max;
}
public:
ran1() {
shuffle_table = new int[table_len];
seedrand(54321);
}
~ran1() {
delete [] shuffle_table;
}
void seedrand(int seed) {
idum = seed;
for (int i = table_len-1; i >= 0; i--) {
propagate();
shuffle_table[i] = idum;
}
next = idum;
}
double frand() {
int i = next/(1 + (int_max-1)/table_len);
next = shuffle_table[i];
propagate();
shuffle_table[i] = idum;
return next/(int_max + 1.0);
}
} rng;
int irand(int top) {
return int(std::floor(rng.frand() * top));
}