Что такое ошибка неопределенной ссылки / неразрешенного внешнего символа и как ее исправить в фортране?

Добавление файлов в ваш проект

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

Лучшая практика

Когда вы добавляете в проект новые файлы исходного кода, давайте им расширение .cpp.

Для пользователей Visual Studio

В Visual Studio кликните правой кнопкой мыши на папке Исходные файлы (Source Files) в окне Обозревателя решений (Solution Explorer) и выберите Добавить (Add) → Создать элемент… (New Item…).

Рисунок 1 – Добавление нового файла в проект в Visual Studio

Убедитесь, что у вас выбран Файл C++ (.cpp). Дайте новому файлу имя, и он будет добавлен в ваш проект.

Рисунок 2 – Создание нового файла в проекте в Visual Studio

Примечание. Если вы создаете новый файл из меню Файл (File), а не из своего проекта в обозревателе решений, новый файл не будет добавлен в ваш проект автоматически. Вам придется добавить его в проект вручную. Для этого кликните правой кнопкой мыши на папке Исходные файлы (Source Files) в окне Обозревателя решений (Solution Explorer) и выберите Добавить (Add) → Существующий элемент (Existing Item), а затем выберите свой файл.

Теперь, когда вы компилируете свою программу, вы должны увидеть, как компилятор перечисляет имя вашего файла при компиляции.

Для пользователей Code::Blocks

В Code::Blocks перейдите в меню File (Файл) и выберите New (Создать) → File… (Файл…).

Рисунок 3 – Создание нового файла в Code::Blocks

В диалоговом окне New from template (Создать из шаблона) выберите C/C++ source (Исходный файл C/C++) и нажмите Go (Перейти).

Рисунок 4 – Создание нового исходного файла C/C++ в Code::Blocks

На этом этапе вы можете увидеть или не увидеть приветствие в диалоговом окне мастера создания исходного файла C/C++. Если да, щелкните Next (Далее).

Рисунок 5 – Диалоговое окно мастера создания исходного файла C/C++

На следующей странице мастера выберите C++ и нажмите Next (Далее).

Рисунок 6 – Выбор языка при создании нового исходного файла в Code::Blocks

Теперь дайте новому файлу имя (не забудьте расширение .cpp) и выберите все конфигурации сборки. Наконец, выберите Finish (Готово).

Рисунок 7 – Указание имени файла и выбор конфигураций сборки

Теперь, когда вы будете компилировать свою программу, вы должны увидеть, как компилятор перечисляет имя вашего файла по мере компиляции.

Для пользователей GCC/G++

Из командной строки вы можете создать дополнительный файл самостоятельно, используя свой любимый редактор, и дать ему имя. Когда вы компилируете свою программу, вам нужно будет включить в строку компиляции все соответствующие исходные файлы. Например:

где main.cpp и add.cpp – это имена ваших исходных файлов, а main – имя выходного файла.

Функции или методы класса определяются в исходных файлах с помощью спецификатора inline.

Пример:-

main.cpp

foo.h (1)

gum.h (1)

foo.cpp (1)

gum.cpp (1)

Если вы укажете, что (аналогично ) является в своем определении, то компилятор встроит (если он выберет), с помощью: —

  • не генерирует никакого уникального определения , и поэтому
  • не испускает никаких символов, с помощью которых компоновщик может ссылаться на определение , и вместо этого
  • замена всех вызовов встроенными копиями скомпилированного тела .

В результате, если вы определяете inline в исходном файле , он компилируется в объектный файл , в котором все вызовы встроены, и не определен символ, с помощью которого компоновщик может ссылаться на . Когда вы связываете в программу вместе с другим объектным файлом, например, , который делает ссылки на внешний символ , компоновщик не может разрешить эти ссылки. Таким образом, связь не работает:

Обобщение:

Ссылка на сайт:

Вы можете определить как , только если компилятор может видеть его определение в каждом исходном файле, в котором может быть вызвано . Это означает, что его встроенное определение должно существовать в файле заголовка , который вы включаете в каждом исходном файле, который вы компилируете, в котором можно вызвать . Сделайте одно из двух:

Либо не включайте определения

Удалите спецификатор из определения исходного файла:

foo.cpp (2)

gum.cpp (2)

Перестройте с этим:

Успех.

или правильно встроенный

Встроенные определения в заголовочных файлах:

foo.h (2)

gum.h (2)

Теперь нам не нужен или :

При связывании с общими библиотеками убедитесь, что используемые символы не скрыты.

Поведение gcc по умолчанию состоит в том, что все символы видны. Однако, когда единицы перевода построены с опцией , только те функции/символы, которые отмечены , являются внешними в результирующем общем объекте.

Вы можете проверить, являются ли символы, которые вы ищете, внешними, вызвав:

скрытые/локальные символы отображаются как с типом символов нижнего регистра, например вместо `T для секции кода:

Вы также можете использовать с опцией , чтобы разобрать имена (если использовался C++).

Подобно Windows-dll, можно было бы пометить публичные функции с помощью определения, например, , определенного как:

Что примерно соответствует Windows/MSVC-версии:

Больше информация о видимости можно найти на вики gcc.

Когда модуль перевода компилируется с помощью , результирующие символы по-прежнему имеют внешнюю связь (показывается символом верхнего регистра в виде ) и могут без проблем использоваться для внешней связи, если объектные файлы становятся частью статических библиотек. Связь становится локальной только тогда, когда объектные файлы связаны в общей библиотеке.

Чтобы определить, какие символы в объектном файле скрыты, выполните:

Интерфейс и реализация

Когда часть программы выделяется в модуль (единицу компиляции), остальной части программы (а если быть точным, то компилятору, который будет обрабатывать остальную часть программы) надо каким-то образом объяснить что имеется в этом модуле. Для этого служат заголовочные файлы.

Таким образом, модуль состоит из двух файлов: заголовочного (интерфейс) и файла реализации.

Заголовочный файл, как правило, имеет расширение .h или .hpp, а файл реализации — .cpp для программ на C++ и .c, для программ на языке C. (Хотя в STL включаемые файлы вообще без расширений, но, по сути, они являются заголовочными файлами.)

Заголовочный файл должен содержать все объявления, которые должны быть видны снаружи. Объявления, которые не должны быть видны снаружи, делаются в файле реализации.

Что может быть в заголовочном файле

Правило 1.

Заголовочный файл может содержать только объявления. Заголовочный файл не должен содержать определения.

То есть, при обработке содержимого заголовочного файла компилятор не должен генерировать информацию для объектного модуля.

Единственным «исключением» из этого правила является определение метода в объявлении класса. Но по стандарту языка, если метод определён в объявлении класса, то для этого метода используется инлайновая подстановка. Поэтому, такое объявление не порождает исполняемого кода — код будет генерироваться компилятором только при вызове этого метода.

Аналогичная ситуация и с объявлением переменных-членов класса: код будет порождаться при создании экземпляра этого класса.

Правило 2.

Заголовочный файл должен иметь механизм защиты от повторного включения.

Защита от повторного включения реализуется директивами препроцессора:

#ifndef SYMBOL
#define SYMBOL

// набор объявлений

#endif

Для препроцессора при первом включении заголовочного файла это выглядит так: поскольку условие «символ  не определён» () истинно, определить символ () и обработать все строки до директивы . При повторном включении — так: поскольку условие » символ  не определён» () ложно (символ был определён при первом включении), то пропустить всё до директивы .

В качестве  обычно применяют имя самого заголовочного файла в верхнем регистре, обрамлённое одинарными или сдвоенными подчерками. Например, для файла header.hтрадиционно используется . Впрочем, символ может быть любым, но обязательно уникальным в рамках проекта.

В качестве альтернативного способа может применяться директива . Однако преимущество первого способа в том, что он работает на любых компиляторах.

Заголовочный файл сам по себе не является единицей компиляции.

Что может быть в файле реализации

Файл реализации может содержать как определения, так и объявления. Объявления, сделанные в файле реализации, будут лексически локальны для этого файла. Т.е. будут действовать только для этой единицы компиляции.

Правило 3.

В файле реализации должна быть директива включения соответствующего заголовочного файла.

Понятно, что объявления, которые видны снаружи модуля, должны быть также доступны и внутри.

Правило также гарантирует соответствие между описанием и реализацией. При несовпадении, допустим, сигнатуры функции в объявлении и определении компилятор выдаст ошибку.

Правило 4.

В файле реализации не должно быть объявлений, дублирующих объявления в соответствующем заголовочном файле.

При выполнении Правила 3, нарушение Правила 4 приведёт к ошибкам компиляции.

Если компиляция завершилась ошибкой

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

Сначала посмотрите на сообщение об ошибке, которое вам выдал компилятор. Чаще всего оно будет содержать номер строки, указывающий, какая строка содержала ошибку. Изучите и эту строку, и строки вокруг нее и убедитесь, что нет опечаток или орфографических ошибок. Также убедитесь, что вы не скопировали в код номера строк.

Во-вторых, посмотрите вопросы и ответы в уроке «0.8 – Несколько распространенных проблем C++», поскольку ваша проблема может быть там освещена.

В-третьих, прочтите комментарии ниже – кто-то мог столкнуться с той же проблемой.

Наконец, если всё вышеперечисленное не помогло, попробуйте поискать сообщение об ошибке в Google. Скорее всего, кто-то уже сталкивался с этим раньше и придумал, как это исправить.

Обозреватель решений Visual Studio

В левой или правой части окна вы должны увидеть окно под названием Обозреватель решений. В этом окне Visual Studio создала для вас решение (решение «HelloWorld»). Внутри него, имя которого выделено жирным шрифтом, находится ваш новый проект (HelloWorld). Visual Studio создала для вас в этом проекте ряд файлов, в том числе HelloWorld.cpp (в элементе дерева Исходные файлы (Source Files)). Вы также можете увидеть некоторые другие файлы .cpp или .h, которые пока можете игнорировать.

Рисунок 8 – Начальные окна Visual Studio 2019

В текстовом редакторе вы увидите, что Visual Studio уже открыла HelloWorld.cpp и создала для вас код. Выделите и удалите весь код и введите/скопируйте следующий код в вашу IDE:

Чтобы скомпилировать программу, либо нажмите F7 (если это не сработает, попробуйте Ctrl + Shift + B), либо перейдите в меню Сборка (Build) → Собрать решение (Build Solution). Если всё пойдет хорошо, вы должны увидеть следующее в окне вывода:

Или, в зависимости от выбранного языка:

Это означает, что ваша компиляция прошла успешно!

Вопрос: У меня вылетела ошибка C1010 («fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add ‘#include «stdafx.h»‘ to your source?»). Что теперь?

Вы забыли отключить предварительно скомпилированные заголовки при создании проекта. Заново создайте свой проект (в соответствии с ) и обязательно отключите предварительно скомпилированные заголовки.

Чтобы запустить скомпилированную программу, нажмите Ctrl + F5 или перейдите в меню Отладка (Debug) и выберите Запуск без отладки (Start Without Debugging). Вы увидите следующее:

Рисунок 9 – Запуск программы

Это результат выполнения вашей программы! Поздравляем, вы скомпилировали и запустили свою первую программу!

Примеры запуска

В результате интерактивного запуска программы выдаётся имя узла, на котором запущен соответствующий процесс, например:

При запуске в пакетном режиме команда запуска программы задаётся либо в скрипте, либо через опцию , например,

или

где скрипт mybat:

Внимание!

  • Команда внутри скрипта может запрашивать ресурсы только в тех пределах, которые установлены командой .
  • Скрипт запускается только на первом из выделенных узлов.
  • Запуск нескольких процессов осуществляется командой . При этом все опции, указанные в командной строке или самом скрипте в строках , приписываются к каждой команде данного скрипта, если не переопределены в ней. Так, результирующий файл приведённого примера будет содержать 2 строки с именами узлов (возможно, одинаковых), на которых выполнятся 2 процесса задачи, сформированные командой srun.
  • Если команды srun запускаются в фоновом режиме (символ в конце строки), то они при наличии ресурсов могут выполняться одновременно.

Теория

Во-первых, несмотря на то, что код ваших программ находится в файлах .cpp, эти файлы добавляются в проект. Проект содержит все необходимые файлы вашей программы, а также сохраняет указанные вами настройки вашей IDE. Каждый раз, при открытии проекта, он запускается с того момента, на котором вы остановились в прошлый раз. При компиляции программы, проект говорит компилятору и линкеру, какие файлы нужно скомпилировать, а какие связать. Стоит отметить, что файлы проекта одной IDE не будут работать в другой IDE. Вам придется создать новый проект (в другой IDE).

Во-вторых, есть разные типы проектов. При создании нового проекта, вам нужно будет выбрать его тип. Все проекты, которые мы будем создавать на данных уроках, будут консольного типа. Это означает, что они запускаются в консоли (аналог командной строки). По умолчанию, консольные приложения не имеют графического интерфейса пользователя — GUI (сокр. от «Graphical User Interface») и компилируются в автономные исполняемые файлы. Это идеальный вариант для изучения языка C++, так как он сводит всю сложность к минимуму.

В-третьих, при создании нового проекта большинство IDE автоматически добавят ваш проект в рабочее пространство. Рабочее пространство — это своеобразный контейнер, который может содержать один или несколько связанных проектов. Несмотря на то, что вы можете добавить несколько проектов в одно рабочее пространство, все же рекомендуется создавать отдельное рабочее пространство для каждой программы. Это намного упрощает работу для новичков.

Традиционно, первой программой на новом языке программирования является всеми известная программа «Hello, world!». Мы не будем нарушать традиции

Когда ваши пути включения отличаются

Ошибки компоновщика могут возникать, когда файл заголовка и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.

Как работают линкеры? Компоновщик сопоставляет объявление функции (объявленное в заголовке) с ее определением (в общей библиотеке), сравнивая их сигнатуры. Вы можете получить ошибку компоновщика, если компоновщик не найдет определение функции, которое идеально соответствует.

Возможно ли все еще получить ошибку компоновщика, даже если объявление и определение, кажется, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете получить такую ​​ситуацию:

Обратите внимание, что хотя оба объявления функций выглядят одинаково в исходном коде, но они действительно различаются в зависимости от компилятора. Вы можете спросить, как человек попадает в такую ​​ситуацию? Включить пути конечно! Если при компиляции разделяемой библиотеки путь включения ведет к , и вы в конечном итоге используете в своей собственной программе, вам останется поцарапать заголовок, задаваясь вопросом, что произошло (каламбур предназначен)

Вы можете спросить, как человек попадает в такую ​​ситуацию? Включить пути конечно! Если при компиляции разделяемой библиотеки путь включения ведет к , и вы в конечном итоге используете в своей собственной программе, вам останется поцарапать заголовок, задаваясь вопросом, что произошло (каламбур предназначен).

Пример того, как это может произойти в реальном мире, объясняется ниже.

Дальнейшая разработка с примером

У меня есть два проекта: и . Оба проекта зависят от . Предположим, библиотека экспортирует следующую функцию:

И тогда вы идете дальше и включаете библиотеку в свой собственный проект.

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

Обратите внимание, что в этом примере компоновщик скажет вам, что он не может найти , когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли бы часами чесать голову, задаваясь вопросом, что пошло не так

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

Отладка компоновщика

DUMPBIN — ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.

Процесс идет так:

Обратите внимание на странное искаженное имя, данное в ошибке компоновщика. (например, draw @ graphics @ XYZ).
Сохраните экспортированные символы из библиотеки в текстовый файл.
Найдите экспортированный символ интереса и обратите внимание, что искаженное имя отличается.
Обратите внимание на то, почему искаженные имена оказались разными

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

Под проектом я имею в виду набор исходных файлов, которые связаны вместе для создания библиотеки или исполняемого файла.

Лучшие сервисы-компиляторы

Компилировать код можно не на жестком диске своего ПК, а онлайн, используя специализированные сервисы. Компилятор находится на сервере разработчика и выполняет все необходимые функции за вас. Правда, функциональность таких сервисов обычно заметно ограничена. Рассчитывать на полную поддержку всех используемых библиотек не стоит, но для быстрого тестирования кода и изучения языка такие компиляторы подходят идеально.

Codepad

Тип: Компилятор

Стоимость: Бесплатно

Поддерживаемые платформы: Любой браузер

Онлайн-сервис для компиляции и интерпретации C++ через браузер, разработанный независимым разработчиком Стивеном Хэйзелом, одним из основателей компании Sauce Labs.

Одним из преимуществ Codepad является функция коллаборации. Можно создавать проекты с собственными субдоменами для приватной совместной работы с коллегами. 

Принцип работы Codepad простой: в текстовое поле сайта нужно вставить сгенерированный ранее код и нажать на кнопку Submit. Утилита в ответ отправит вывод (результат работы) команды. Потом можно оставить комментарий под написанным кодом и сгенерировать постоянную ссылку для взаимодействия с другими программистами.

Также Codepad поддерживает C, Haskell, Lua, Python и другие языки, над которыми можно работать в команде прямо из браузера. 

CPP.sh

Тип: Компилятор

Стоимость: Бесплатно

Поддерживаемые платформы: Любой браузер

Еще одна онлайн-альтернатива для тех, кто хочет разрабатывать ПО на языке C++ и кому нужен простой и быстрый компилятор.

Интерфейс CPP.sh состоит из двух ключевых фрагментов: текстовое поле, куда можно прописать код, и панель с настройками. Текстовый редактор сервиса поддерживает подсветку синтаксиса и возможность протестировать практически любой код прямо в браузере, не используя дополнительное ПО. 

В настройках можно выбрать стандарт языка (С++98, С++11, С++14), тип уведомлений об ошибках (Wall, Wextra, Wpedantic), уровень оптимизации кода, а также прописать параметры инициализации кода и вывода данных. Также в CPP.sh есть две консоли с информацией о компиляции и запуске кода. 

Jdoodle

Тип: Компилятор

Стоимость: Бесплатно 

Поддерживаемые платформы: Браузер, iOS и Android

Еще один компилятор С++, работающий в браузере и не требующий установки дополнительного ПО. 

В Jdoodle можно инициализировать код в одном из пяти доступных режимов: GCC 5.3.0, Zapcc 5.0.0, GCC 7.2.0, GCC 8.1.0, GCC 9.1.0. Можно вписать свои аргументы для командной строки и ввести параметры Stdin Inputs. 

Jdoodle работает в двух режимах: первый – статичный (сначала пишете код, а потом его запускаете), второй – интерактивный (результат любого действия разработчика тут же отображается в консоли).

При необходимости можно не писать код на сайте, а загрузить файл уже с готовым скриптом. Также в Jdoodle можно включить темную тему, выбрать размер шрифта, сохранить проект в отдельном файле и пригласить коллег для совместной работы. А еще у Jdoodle есть мобильная версия для компиляции на смартфонах и планшетах.

C++ Tutor

Тип: Компилятор

Стоимость: Бесплатно

Поддерживаемые платформы: Любой браузер

Последняя в подборке система визуализации кода, часто использующаяся начинающими разработчиками на ранних этапах изучения С++. В отличие от вышеперечисленных компиляторов, здесь все предельно просто: вводите код, затем нажимаете на кнопку «Visualize Execution» и смотрите на результат. Никаких настроек, опций и дополнительных функций тут нет. Максимально примитивный, но все еще эффективный инструмент. 

Пример с несколькими файлами

В уроке «2.6 – Предварительные объявления и определения» мы рассмотрели программу с одним исходным файлом, которая не компилируется:

Когда компилятор достигает вызова функции в строке 5 в функции , он не знает, что такое , потому что мы определили только в строке 9! Нашим решением было либо переупорядочить функции (поместив сначала ), либо использовать для предварительное объявление.

Теперь посмотрим на аналогичную программу из нескольких исходных файлов:

add.cpp:

main.cpp:

Ваш компилятор может решить сначала скомпилировать либо add.cpp, либо main.cpp. В любом случае main.cpp не скомпилируется, что приведет к той же ошибке компилятора, что и в предыдущем примере:

Причина точно такая же: когда компилятор достигает строки 5 файла main.cpp, он не знает, что такое идентификатор .

Помните, что компилятор компилирует каждый файл отдельно. Он не знает о содержимом других исходных файлов и не запоминает что-либо, что он видел из ранее скомпилированных исходных файлов. Таким образом, даже если компилятор, возможно, видел определение функции ранее (если он сначала скомпилировал add.cpp), он этого не запомнил.

Эта ограниченная видимость и короткая память являются преднамеренными, чтобы файлы могли иметь функции или переменные, у которых одинаковые имена, но которые не конфликтуют друг с другом. В следующем уроке мы рассмотрим пример такого конфликта.

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

Лучшее решение здесь – использовать предварительное объявление:

main.cpp (с предварительным объявлением):

add.cpp (остается прежним):

Теперь, когда компилятор компилирует main.cpp, он будет знать, что такое идентификатор , и будет удовлетворен. Линкер соединит вызов функции в main.cpp с определением функции в add.cpp.

Используя этот метод, мы можем предоставить файлам доступ к функциям, которые находятся в другом файле.

Попробуйте скомпилировать add.cpp и main.cpp с предварительным объявлением. Если вы получили ошибку линкера, убедитесь, что вы правильно добавили add.cpp в свой проект или строку компиляции.

Опции

если число процессов (tasks) не задано, то по умолчанию n=1.

при отсутствии заказа времени для решения задачи выделяется по умолчанию 30 минут. Максимальное время для счета задачи:

20 часов — в будние дни (с 9 часов понедельника до 16 часов пятницы);
85 часов — на выходные (с 16 часов пятницы до 9 часов понедельника плюс 20 часов), т.е. на 85 часов задача запустится, если она войдет в решение в 16 часов ближайшей пятницы, иначе будет ждать следующей; аналогично, на 84 часа есть шанс запустить до 17 часов пятницы и т.д

до 9 часов понедельника;
100 часов — если к выходным добавляются праздничные дни.
Время может быть задано в виде:

минуты
минуты:секунды
часы:минуты:секунды
дни-часы
дни-часы:минуты
дни-часы:минуты:секунды

задает число узлов (nodes) для задачи, если пользователю это важно.

Для увеличения оперативной памяти можно воспользоваться опциями:

задаёт минимальную память в расчёте на одно ядро в мегабайтах ; если не задано, то по умолчанию 1 ГБ;
задаёт память на узле в мегабайтах.
Эти опции взаимно исключают друг друга.
задаёт запуск программы на узлах с GPU. Если не задан, то количество GPU=0, т.е

GPU при счете не используются. Если не указан тип GPU, то автоматически назначается младшая модель (m2090). Типы GPU в 2020 году m2090, k40m, v100

или позволяет указать раздел (partition) кластера для запуска задачи.
Основные разделы: tesla, apollo, v100 и debug. Эти разделы покрывают весь кластер и взаимно не пересекаются, т.е. содержат разные узлы (см. Кластер «Уран»). Список всех разделов выдается командой .
Если раздел не задан пользователем явно, то по умолчанию будет выбран раздел apollo, но при отсутствии в нем нужного числа свободных процессоров будет задействован раздел tesla. позволяет запускать задачи в специально выделенном для отладки программ разделе debug с максимальным временем счета 30 минут. Например,

Опции , , позволяют более гибко регулировать список узлов, допустимых для запуска задачи (см. ).

Например:

  • — выделить заданию ресурсы узлов tesla5, tesla6, tesla7, tesla15, а если на них не хватит, то и другие узлы;
  • — не выделять заданию ресурсы узла tesla22;
  • — выделять задаче только те узлы, которые имеют ресурс с именем (Feature), указанным после . На кластере имеются ресурсы с именами: tesla, a2017, a2019 (поколения узлов); bigmem (узлы с большим объёмом ОЗУ).
    Информацию о том, какие ресурсы есть на конкретном узле, можно получить командой вида .

Описание всех опций и примеры команд можно посмотреть в руководстве man с помощью команд:

По умолчанию стандартный вывод пакетной задачи и стандартный поток ошибок направляются в файл с именем slurm-%j.out, где %j заменяется уникальным идентификатором (номером) задачи.
Перенаправление ввода-вывода можно выполнить, указав программе sbatch опции

При задании имени файла (filename pattern) можно использовать символы замены, в частности, заменяется на JobID, — на номер процесса в рамках задания. Таким образом при каждом запуске задачи сгенерирует уникальные имена для каждого процесса.

Выдаваемые результаты конкретной команды srun можно поместить вместо стандартного в указанный файл, добавив после команды символ перенаправления вывода .

Можно (чаще, при интерактивном запуске) параллельно просматривать результаты и сохранять их в файле, например:

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: