Целочисленная арифметическая производительность 32 против 64-битных - PullRequest
4 голосов
/ 31 января 2012

У меня есть 2 машины с F # 2.0 Интерактивная сборка 4.0.30319.1 по сравнению с 2010 г. Некоторые из моих программ работали значительно медленнее на более быстрой машине. Похоже, проблема заключается в том, что целочисленная арифметическая производительность в 32-разрядной версии Windows значительно ниже, чем в 64-разрядной версии Windows.

На чуть более медленной 64-битной машине с Windows 7 (программа указана ниже):

primeCount = 1270607
Действительный: 00: 00: 07.553, ЦП: 00: 00: 07.519, GC gen0: 0, gen1: 0, gen2: 0

На немного более быстрой машине с Windows XP SP2:

primeCount = 1270607
Действительный: 00: 00: 32.800, ЦП: 00: 00: 32.796, GC gen0: 0, gen1: 0, gen2: 0

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

Программа:

let isPrime(n) =
    if n < 2 then false
    elif (n % 2) = 0 then                   // take care of even case
        if n = 2 then true
        else false
    else                                    // n is odd
        let ms = int(sqrt(float(n)))
        let rec isPrimeUtil(m) =
            if m > ms then true
            elif n % m = 0 then false
            else isPrimeUtil(m + 2)
        isPrimeUtil(3)

let nums = [1 .. 20000000]
let pcountref = ref 0                       // # of primes found

let primeCount =
    pcountref := 0
    for x in nums do
        if (isPrime x) then incr pcountref

do primeCount
printfn "primeCount = %d" !pcountref

Отправьте программу в интерактив. #time;; Затем, чтобы измерить истекшее время обработки, а не генерацию номеров диапазонов, выберите строку

let pcountref = ref 0

и все последующие строки и отправьте в интерактив.

Ответы [ 3 ]

3 голосов
/ 31 января 2012

Я думаю, что более вероятное объяснение состоит в том, что 64-битный JIT выполняет оптимизацию хвостового вызова, а 32-битный JIT - нет.Функция isPrimeUtil может быть оптимизирована

Обратите внимание, что в данном примере BigInteger все равно не используется, также есть место для улучшения алгоритмов - сито будет работать намного быстрее

1 голос
/ 31 января 2012

float является 64-битным, так что вызов sqrt(float(n)), вероятно, ваш спад производительности.(И объяснил бы, почему 64-битная машина справляется с этим гораздо лучше.)

Попробуйте float32, если вам не нужна точность / *.

См .: http://msdn.microsoft.com/en-us/library/dd233210.aspx

У меня нет 32-битной машины для тестирования, но на моей 64-битной машине просто тестирование кода sqrt занимает достаточно много времени.

let nums = [1 .. 20000000]

let ans = List.map (fun n -> int(sqrt(float(n))) nums

Дает реальное время 5,120 с, что являетсязначительная часть вашего времени исполнения.

0 голосов
/ 31 января 2012

Эти результаты имеют смысл. Реализации BigNum часто используют машинное целое число, пока не обнаружат переполнение, а затем переключатся на более сложное представление. 64-разрядные целые числа могут содержать гораздо большие значения, чем 32-разрядные целые числа. Ваша тестовая программа, вероятно, тратит гораздо больше времени на выполнение быстрой машинной арифметики, когда она работает на 64-битной системе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...