gfortran: недопустимая директива препроцессора и ошибки компиляции недопустимого символа/нечислового символа

Поэтому я пытаюсь использовать тесты NAS для тестирования производительности в конкретной реализации MPI. Итак, я пошел компилировать код на Фортране и наткнулся на барьер. Всякий раз, когда я ввожу эту команду для компиляции:

gfortran -O0 -Wall -I/home/stephen/trunk/include -I.  -c ./TestData/common/timers.f

Я получаю эти ошибки компилятора:

Warning: mpif.h:2: Illegal pdreprocessor directive
Warning: mpif.h:3: Illegal preprocessor directive
Warning: mpif.h:4: Illegal preprocessor directive
Warning: mpif.h:5: Illegal preprocessor directive
Warning: mpif.h:6: Illegal preprocessor directive
Warning: mpif.h:7: Illegal preprocessor directive
Warning: mpif.h:8: Illegal preprocessor directive
Warning: mpif.h:9: Illegal preprocessor directive
Warning: mpif.h:12: Illegal preprocessor directive
Warning: mpif.h:13: Illegal preprocessor directive
Warning: mpif.h:14: Illegal preprocessor directive
Warning: mpif.h:2: Illegal preprocessor directive
Warning: mpif.h:3: Illegal preprocessor directive
Warning: mpif.h:4: Illegal preprocessor directive
Warning: mpif.h:5: Illegal preprocessor directive
Warning: mpif.h:6: Illegal preprocessor directive
Warning: mpif.h:7: Illegal preprocessor directive
Warning: mpif.h:8: Illegal preprocessor directive
Warning: mpif.h:9: Illegal preprocessor directive
Warning: mpif.h:12: Illegal preprocessor directive
Warning: mpif.h:13: Illegal preprocessor directive
Warning: mpif.h:14: Illegal preprocessor directive
mpif.h:1.1:
    Included at ./TestData/common/timers.f:30:

/*
 1
Error: Non-numeric character in statement label at (1)
mpif.h:1.2:
    Included at ./TestData/common/timers.f:30:

/*
  1
Error: Invalid character in name at (1)
mpif.h:1.1:
    Included at ./TestData/common/timers.f:50:

/*
 1
Error: Non-numeric character in statement label at (1)
mpif.h:1.2:
    Included at ./TestData/common/timers.f:50:

/*
  1
Error: Invalid character in name at (1)
make: *** [cg] Error 1

Вот ошибочный код timers.f (строки 30 и 50 являются строками включения):

c---------------------------------------------------------------------                                                                                                                                         
c---------------------------------------------------------------------                                                                                                                                         
      subroutine timer_start(n)
c---------------------------------------------------------------------                                                                                                                                         
c---------------------------------------------------------------------                                                                                                                                         
      implicit none
      integer n
      include 'mpif.h'
      double precision start(64), elapsed(64)
      common /tt/ start, elapsed
      start(n) = MPI_Wtime()
      return
      end
c---------------------------------------------------------------------                                                                                                                                         
c---------------------------------------------------------------------                                                                                                                                         
      subroutine timer_stop(n)
c---------------------------------------------------------------------                                                                                                                                         
c---------------------------------------------------------------------                                                                                                                                         
      implicit none
      integer n
      include 'mpif.h'
      double precision start(64), elapsed(64)
      common /tt/ start, elapsed
      double precision t, now
      now = MPI_Wtime()
      t = now - start(n)
      elapsed(n) = elapsed(n) + t
      return
      end

Любые идеи? Я перепробовал всевозможные аргументы командной строки для gfortran, чтобы попытаться заставить его выполнять различные типы предварительной обработки (большинство из них были сделаны вслепую, я признаю). Странно для меня то, что компилятор ошибается с нечисловыми символами /*, которых нет нигде в моем коде, так что я совсем запутался.

Спасибо!


person SteVwonder    schedule 12.06.2012    source источник
comment
Попробуйте изменить суффикс файла, который вы используете, с .f на .f90 и начальный символ строки комментария с c на !   -  person High Performance Mark    schedule 12.06.2012
comment
Какую реализацию MPI вы используете?   -  person mgilson    schedule 12.06.2012
comment
Можете ли вы опубликовать несколько строк с начала включенного mpif.h?   -  person Hristo Iliev    schedule 13.06.2012
comment
mpif.h подозрительно похож на заголовок C. Вы никогда не должны импортировать это в исходный файл Fortran.   -  person talonmies    schedule 13.06.2012
comment
@talonmies: хотя я согласен с вашим утверждением, программы Fortran MPI очень часто используют include mpif.h, а не use mpi. mpi-f-for-fortran.   -  person High Performance Mark    schedule 13.06.2012
comment
@HighPerformanceMark, вот что я получил: mpif.h:22: включено в ./TestData/common/timers.f90:50: C 1 Error: неклассифицируемый оператор в (1) И я проверил строку 22 mpif.h и там там нет ничего необычного. А строка 50 файла timers.f90 — это оператор включения.   -  person SteVwonder    schedule 13.06.2012
comment
@HighPerformanceMark -- open-mpi.org/papers/euro-pvmmpi -2005-fortran -- Это огромное количество интерфейсов, которые необходимо сгенерировать для создания полного модуля mpi, вероятно, является одной из причин, по которой многие коды по-прежнему include 'mpif.h' вместо use mpi   -  person mgilson    schedule 13.06.2012
comment
@mgilson, это было в 2005 году. Сейчас компиляторы работают намного быстрее. Даже если генерация всех интерфейсов Fortran займет целую вечность, добавленная проверка аргументов — это огромная вещь. Одна из наиболее распространенных ошибок, которую допускают программисты на смешанных языках C/Fortran, заключается в том, что они пропускают аргумент вывода ошибки. Если используется include 'mpif.h', компилятор не будет жаловаться, и программа, скорее всего, загадочным образом выйдет из строя во время выполнения. Если используется use mpi, произойдет ошибка компиляции. Причина, по которой этот конкретный код использует include, заключается в том, что он совместим с F77.   -  person Hristo Iliev    schedule 13.06.2012
comment
@HristoIliev - Да, эта статья устарела, но я думаю, что проблема все еще существует (OpenMPI по-прежнему генерирует только частичный интерфейс, если в configure не указано иное). Я согласен, что проверка аргументов огромна. У меня было несколько программ, которые не зависали таинственным образом во время выполнения (просто давали неправильные результаты) из-за ошибок, подобных той, которую вы описали выше. К счастью, компиляторы все лучше диагностируют и такого рода ошибки. Также обратите внимание, что include также не является стандартным F77 — он не был добавлен до F90.   -  person mgilson    schedule 13.06.2012
comment
@mgilson, строго говоря, implicit none также не является стандартным F77 и строчными буквами. Но многие компиляторы F77 реализовали почти стандартные расширения, которые позже нашли свое применение в стандарте F90. Я хотел сказать, что этот код предназначен для компиляции даже с более старыми компиляторами до F90. И, кстати, опускание ierr в mpi_init приводит к ошибкам Open MPI 1.6 как с gfortran 4.7, так и с ifort 12.1 — довольно свежими компиляторами. Извините за не по теме.   -  person Hristo Iliev    schedule 13.06.2012


Ответы (2)


Вы определенно компилируете этот код нестандартным способом. Обычный способ компиляции кода f77 или f90 с помощью mpi заключается в использовании программ mpif77 или mpif90, которые обертывают компилятор, используемый для создания конкретной версии MPI.

Например, на моем ноутбуке (с использованием OpenMPI, скомпилированного с помощью gfortran/gcc) команда mpif77 примерно эквивалентна:

gfortran -I/usr/local/include -L/usr/local/lib -lmpi_f77 -lmpi -lopen-rte -lopen-pal -lutil

(Я получил эту информацию через mpif90 -showme - я не знаю, является ли этот параметр командной строки частью стандарта MPI, поэтому он может не сработать для вас).

чтобы скомпилировать ваш код, я бы попробовал что-то вроде этого:

mpif77 -O0 -Wall -c ./TestData/common/timers.f -o timers.o

Поскольку других файлов для включения нет, на самом деле нет смысла увеличивать путь включения компилятора с помощью дополнительных флагов -I - вы просто увеличиваете вероятность того, что вы случайно найдете неправильный заголовочный файл;).

Возможно, в вашем текущем каталоге или в /home/stephen/trunk/include есть файл «mpif.h», который выбирается, когда не должен. (Похоже, вы можете видеть заголовок C, поскольку /* — это начало комментария C, хотя я не понимаю, почему файл заголовка c должен называться «mpif.h»).

person mgilson    schedule 12.06.2012
comment
Опции определенно не являются стандартом MPI и зависят от реализации. - person Vladimir F; 13.06.2012
comment
-Я. и -I/home/stephen/include являются переменными в make-файле, поэтому, когда вы запускаете make cg, он выглядит так, как я написал. mpif.h существует в /home/stephen/include, поэтому он там и является единственным файлом с таким именем на машине. - person SteVwonder; 13.06.2012
comment
Кроме того, причина, по которой все делается нестандартным образом, заключается в том, что целью проекта является создание собственной версии MPI, которая допускает избыточность и высокую частоту отказов, в конечном итоге для использования на BOINC. Я не писал ничего из этого кода, я просто пытаюсь его скомпилировать и запустить (и поймите человека, который его написал, с которым мы потеряли контакт). Так что я не думаю, что mpif77 подойдет для моей проблемы, но я все равно попробую. - person SteVwonder; 13.06.2012
comment
Я только что нашел дубликат mpif.h. Так что все это время я редактировал не тот. @mgilson, ты был прав. Спасибо! - person SteVwonder; 13.06.2012
comment
@SteVwonder - рад помочь. Имеет смысл написать реализацию mpi с избыточностью — когда у вас есть 100 000 узлов, я уверен, что вероятность того, что ни один узел не выйдет из строя в течение часа, значительно падает. Удачи! - person mgilson; 13.06.2012

Я согласен с тем, что вы должны использовать mpif77 или mpif90 для ссылки на нужные библиотеки. Если gfortran не любит макросы препроцессора, попробуйте опцию компилятора -cpp.

person Vladimir F    schedule 12.06.2012
comment
К сожалению, добавление параметра компилятора -cpp ничего не дает. Точно такие же ошибки, как и раньше. - person SteVwonder; 13.06.2012
comment
Да не мог. Я не знал, что cpp не обрабатывает включенные файлы, а только файлы #include. - person Vladimir F; 13.06.2012