Подтвердить что ты не робот

Fortran встроенные процедуры синхронизации, что лучше? cpu_time или system_clock

При синхронизации программы FORTRAN я обычно использую команду call cpu_time(t).
Затем я наткнулся на call system_clock([count,count_rate,count_max]), который, похоже, делает то же самое. Однако в более сложной усадьбе. Мое знание об этом происходит из: старой документации Intel.
Я не смог найти его на главной странице Intel. См. Мою разметку ниже.

  • Какой из них более точный, или они похожи?
  • Убирает ли один из них промахи в кеше (или другие), а другой нет или делает их?
  • Или это единственная разница в том, что отмеченная вещь в моей разметке ниже?

Это мои вопросы, ниже я предоставил код для просмотра некоторых таймингов и обычаев. Они показали мне, что они очень похожи на результат и, похоже, похожи на реализацию.
Я должен отметить, что я, вероятно, всегда буду придерживаться cpu_time, и мне не нужны более точные тайминги.

В приведенном ниже коде я попытался их сравнить. (я также пробовал более сложные вещи, но не буду поставлять, чтобы сохранить краткость) Поэтому в основном мой результат таков:

  • cpu_time
    • Прост в использовании, вам не нужны вызовы инициализации
    • Прямое время в разнице
    • Также должен быть специфичным для компилятора, но нет возможности увидеть точность. (норма - миллисекунды).
    • Это сумма времени потока. То есть не рекомендуется для параллельных прогонов.
  • system_clock
    • Требуется предварительная инициализация.
    • Послепроцесс, в виде деления. (маленькая вещь, но тем не менее разница)
    • Является компилятором конкретным. На моем ПК было найдено следующее:
      • Intel 12.0.4 использует скорость счета 10000 из-за точности INTEGER.
      • gcc-4.4.5 использует 1000, не знаю, как это отличает
    • Является склонным к встрече с wraparounds, т.е. если c1 > c2, из-за count_max
    • Время от одного стандартного времени. Таким образом, это даст фактическое время одного потока, а не суммы.

Код:

PROGRAM timer
  IMPLICIT NONE
  REAL :: t1,t2,rate 
  INTEGER :: c1,c2,cr,cm,i,j,n,s
  INTEGER , PARAMETER :: x=20000,y=15000,runs=1000
  REAL :: array(x,y),a_diff,diff

  ! First initialize the system_clock
  CALL system_clock(count_rate=cr)
  CALL system_clock(count_max=cm)
  rate = REAL(cr)
  WRITE(*,*) "system_clock rate ",rate

  diff = 0.0
  a_diff = 0.0
  s = 0
  DO n = 1 , runs
     CALL CPU_TIME(t1)
     CALL SYSTEM_CLOCK(c1)
     FORALL(i = 1:x,j = 1:y)
        array(i,j) = REAL(i)*REAL(j) + 2
     END FORALL
     CALL CPU_TIME(t2)
     CALL SYSTEM_CLOCK(c2)
     array(1,1) = array(1,2)     
     IF ( (c2 - c1)/rate < (t2-t1) ) s = s + 1
     diff = (c2 - c1)/rate - (t2-t1) + diff
     a_diff = ABS((c2 - c1)/rate - (t2-t1)) + a_diff
  END DO

  WRITE(*,*) "system_clock : ",(c2 - c1)/rate
  WRITE(*,*) "cpu_time     : ",(t2-t1)
  WRITE(*,*) "sc < ct      : ",s,"of",runs
  WRITE(*,*) "mean diff    : ",diff/runs
  WRITE(*,*) "abs mean diff: ",a_diff/runs
END PROGRAM timer

Чтобы завершить здесь, я приведу результаты моего компилятора Intel 12.0.4 и gcc-4.4.5.

  • Intel 12.0.4 с -O0

    system_clock rate    10000.00    
    system_clock :    2.389600    
    cpu_time     :    2.384033    
    sc < ct      :            1 of        1000
    mean diff    :   4.2409324E-03
    abs mean diff:   4.2409897E-03
    
    real    42m5.340s
    user    41m48.869s
    sys 0m12.233s
    
  • gcc-4.4.5 с -O0

    system_clock rate    1000.0000    
    system_clock :    1.1849999    
    cpu_time     :    1.1840820    
    sc < ct      :          275 of        1000  
    mean diff    :   2.05709646E-03  
    abs mean diff:   2.71424348E-03  
    
    real    19m45.351s  
    user    19m42.954s  
    sys 0m0.348s  
    

Спасибо за чтение...

4b9b3361

Ответ 1

Эти два внутренних отчета сообщают о разных типах времени. system_clock сообщает "время на стене" или прошедшее время. cpu_time сообщает время, используемое процессором. На многозадачной машине они могут быть очень разными, например, если ваш процесс поделился процессором одинаково с тремя другими процессами и, следовательно, получил 25% от CPU и использовал 10 cpu секунд, потребуется около 40 секунд фактического истекшего или настенного время в часах.

Ответ 2

cpu_time() обычно имеет разрешение около 0,01 секунды на процессорах, совместимых с Intel. Это означает, что меньший интервал времени может считаться нулевым временем. Большинство современных компиляторов для linux делают разрешение system_clock() зависящим от типов данных аргументов, поэтому integer (int64) даст более 1 микросекундного разрешения, а также разрешает подсчет за значительный промежуток времени. gfortran для Windows был изменен в последнее время (в течение 2015 года), чтобы сделать system_clock() эквивалентным вызовам query_performance. ifort Windows, тем не менее, по-прежнему показывает примерно 0,01 разрешения для system_clock, даже после того, как omp_get_wtime был изменен для использования query_performance. Я бы отменил предыдущие комментарии об измерении разрешения cpu_time или system_clock в тактовых импульсах, особенно если это можно считать относящимся к тикам процессора или данных, например, инструкция rdtsc может сообщить.

Ответ 3

Я нахожу itime (см. gfortran manual), чтобы быть хорошей альтернативой system_clock для выбора времени для трансляционных программ. Он очень прост в использовании:

integer, dimension(3) :: time
call itime(time)
print *, 'Hour:  ', time(1)
print *, 'Minute:', time(2)
print *, 'Second:', time(3)

Ответ 4

Я нахожу secnds() как самый простой способ получить время на стене. Его использование почти идентично cpu_time().

real(8)::t1,delta
t1=secnds(0.0)
!Do stuff
delta=seconds(t1)