Параметры настройки системы Pharo

Я новичок в Stackru и ищу советы и помощь по настройке Pharo 5.0 в среде Windows.

Мой ПК работает под управлением Windows 10, CPU I5-4670K с частотой 4 ГГц и SSD Plextor 512G в качестве диска C, на котором загружается и работает Pharo 5.0.

Ниже приведен набор кодов, которые я использовал для понимания поведения Pharo как в плане производительности, так и в отношении точности вычислений.

  | x y |
  x := 0.
  y := 400000000.
  [1 to: 2000000000 do: [ :i | 
      x := x + 0.2]] timeToRun

Выполнено 2 минуты 8,281 секунды. Если я выбил один ноль из числа итераций, это заняло всего 1.762 секунды. В 10 раз больше итераций использовалось более 70 раз во время выполнения. Кажется, что я попал в системную границу, так что время выполнения между этими двумя случаями вырастет намного больше, чем в 10 раз.

Цените любые советы и помогите настроить виртуальную машину Pharo 5.0, чтобы я мог уменьшить такое неожиданное и нежелательное поведение системы?

ps Во время выполнения диспетчер задач Windows не сообщал об изменениях активности диска. Практически все операции выполняются с использованием оперативной памяти и процессора. Кстати, если у вас нет намного более быстрого ПК, пожалуйста, не пытайтесь добавить еще один ноль к числу итераций, это заняло так много времени, что мне пришлось прервать выполнение.

1 ответ

Решение

Добро пожаловать на SO (и на тег smalltalk!)

Первое замечание, что временное y здесь не играет никакой роли, поэтому мы можем немного упростить фрагмент

| x |
x := 0.
[1 to: 200000000 * 10 do: [ :i | 
  x := x + 0.2]] timeToRun

с которым вы сравнили

| x |
x := 0.
[1 to: 200000000 * 1 do: [ :i | 
  x := x + 0.2]] timeToRun

Причина, по которой первая версия не просто 10 раз медленнее, чем второй, что в первом блок переменной i движется от SmallInteger домен к LargeInteger один. Таким образом, каждый раз, когда блок увеличивается i, когда i превзошел SmallInteger граница, сложение i := i + 1 что происходит здесь включает в себя LargeInteger арифметика, которая медленнее, чем SmallInteger один.

И сколько раз LargeInteger арифметика состоится? Ну, чтобы вычислить, что нам нужно только вычесть SmallInteger maxVal от 200000000 * 10:

(200000000 * 10) - SmallInteger maxVal  = 926,258,177

это означает, что Pharo выполняет такое количество операций с большим целым i,

Обратите внимание, что если бы мы имели вместо

| x |
x := 0.
[
  10 timesRepeat: [1 to: 200000000 * 1 do: [ :i | x := x + 0.2]]
] timeToRun

мы бы потратили около 10 раз скорость одной итерации.


ДОПОЛНЕНИЕ

Пожалуйста, не принимайте объяснение выше, как предполагающее, что LargeInteger арифметика имеет плохую производительность в Pharo. Напротив, Pharo делает большую работу по обеспечению эффективности таких вычислений.

За кулисами Pharo использует примитивы для этих операций, предоставляя программисту уникальное и последовательное представление и API Integer арифметика. На самом деле, если вы попытаетесь сделать то же самое на другом диалекте без поддержки VM для LargeInteger вам придется ждать намного (намного) дольше, чтобы результат был рассчитан.

Другие вопросы по тегам