Сравнительный анализ этого класса:
struct Sieve {
std::vector<bool> isPrime;
Sieve (int n = 1) {
isPrime.assign (n+1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= (int)sqrt((double)n); ++i)
if (isPrime[i])
for (int j = i*i; j <= n; j += i)
isPrime[j] = false;
}
};
Я получаю более 3-кратную худшую производительность (процессорное время) с 64-битной бинарной или 32-разрядной версией (выпускной сборкой) при вызове конструктора для большого числа, например.
Sieve s(100000000);
Я тестировал sizeof(bool), и для обеих версий это 1.
Когда я заменяю vector<bool> на vector<char>, производительность становится одинаковой для 64-разрядных и 32-разрядных версий. Почему это?
Вот время выполнения для S(100000000) (режим выпуска, 32-разрядный первый, 64-битный второй)):
vector<bool> 0,97 с 3,12 с
vector<char> 0,99 с 0,99 с
vector<int> 1,57 с 1,59 с
Я также провел тест на чувствительность с VS2010 (вызванный ответом Wouter Huysentruit), который произвел 0,98 с 0,88. Итак, что-то не так с реализацией VS2012.
Я отправил отчет об ошибке в Microsoft Connect
ИЗМЕНИТЬ
Многие ответы ниже содержат комментарии о недостатках использования int для индексирования. Это может быть правдой, но даже сам Великий Волшебник использует стандартный for (int i = 0; i < v.size(); ++i) в своих книгах, поэтому такой шаблон не должен нести существенного штрафа за производительность. Кроме того, эта проблема была поднята во время конференции Going Native 2013, и председательствующая группа гуру С++ прокомментировала их ранние рекомендации по использованию size_t для индексирования и как возвращаемый тип size() как ошибку. Они сказали: "Мы сожалеем, мы были молоды..."
Название этого вопроса может быть перефразировано до: Более 3-кратного снижения производительности этого кода при обновлении с VS2010 до VS2012.
ИЗМЕНИТЬ
Я сделал грубую попытку найти выравнивание памяти индексов i и j и обнаружил, что эта инструментальная версия:
struct Sieve {
vector<bool> isPrime;
Sieve (int n = 1) {
isPrime.assign (n+1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= sqrt((double)n); ++i) {
if (i == 17) cout << ((int)&i)%16 << endl;
if (isPrime[i])
for (int j = i*i; j <= n; j += i) {
if (j == 4) cout << ((int)&j)%16 << endl;
isPrime[j] = false;
}
}
}
};
автоматически запускается быстро (только на 10% медленнее, чем 32-разрядная версия). Это и производительность VS2010 затрудняют принятие теории оптимизатора, имеющей неотъемлемые проблемы с индексами int вместо size_t.