Решение: Очевидно, виновником было использование 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));
}