Инициализация будет перечислять всегда быть обработанной перед кодом конструктора?

1180 Безусловно, это было бы наиболее эффективным использованием ресурсов. Позвольте мне предупредить вас: в этом много деталей; Я постараюсь перечислить столько, сколько вы получите. Я рекомендую вам добавить собственный исчерпывающий ответ, в котором перечислены все проблемы, с которыми вы столкнулись, и способ их обхода (как только вы это сделаете)


В отношении создания / прекращения работы кластера

  • [1182 ] Для создания и завершения кластера у вас есть EmrCreateJobFlowOperator и EmrTerminateJobFlowOperator соответственно

  • Не беспокойтесь, если вы не используете AWS SecretAccessKey (и полностью полагаться на IAM роли ); создание любого AWS -связанного hook или operator в Airflow будет автоматически отступать к базовой EC2 роли IAM

  • Если вы НЕ используете EMR-Steps API для передачи задания, то вам также придется вручную определить обе вышеуказанные операции, используя Sensors ] . Уже есть датчик для фазы создания опроса, который называется EmrJobFlowSensor , и вы можете слегка изменить его, чтобы создать датчик для завершения

  • Вы передаете свой кластер-конфигурацию JSON в job_flow_extra . Вы также можете передавать конфиги в параметре Connection (например, my_emr_conn) extra , но воздерживаться от него, потому что он часто прерывает загрузку SQLAlchemy ORM (так как это большая json)


Относительно отправки заданий

  • Вы либо отправляете задания в Emr, используя EMR-Steps API , что можно сделать либо на этапе создания кластера (в JSON Cluster-Configs), либо впоследствии, используя add_job_flow_steps() . Есть даже emr_add_steps_operator() в Airflow, который также требует EmrStepSensor . Вы можете прочитать больше об этом в AWS документах , и вам, возможно, также придется использовать command-runner.jar

  • Для конкретных случаев применения (например, Hive, Livy), вы можете использовать их конкретные способы. Например, вы можете использовать HiveServer2Hook , чтобы отправить Hive задание. Вот сложная часть: вызов run_job_flow() (сделанный на этапе создания кластера) дает вам только job_flow_id (идентификатор кластера). Вам нужно будет использовать вызов describe_cluster() , используя EmrHook , чтобы получить private-IP главного узла . Используя это, вы сможете программно создать Connection (например, Hive Server 2 Thrift соединение ) и использовать его для отправки ваших вычислений в кластер. И не забудьте удалить эти соединения (для удобства) до завершения рабочего процесса.

  • Наконец, есть старый добрый bash для взаимодействия с кластером. Для этого вы также должны передать пару ключей EC2 на этапе создания кластера . После этого вы можете программно создать SSH соединение и использовать его (с SSHHook или SSHOperator ) для выполнения заданий в кластере. Узнайте больше о SSH-материалах в Airflow здесь

  • Особенно для отправки Spark заданий на удаленных Emr кластера, прочитайте это обсуждение


15
задан Frank 7 April 2009 в 02:29
поделиться

3 ответа

Да, это будет, согласно C++11: 12.6.2 /10 (тот же раздел в C++14, 15.6.2 /13 в C++17):


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

  • Во-первых, и только для конструктора большей части производного класса (1.8), виртуальные базовые классы инициализируются в порядке, они появляются на в глубину слева направо обход направленного графа без петель базовых классов, где “слева направо” порядок появления базовых классов в основном списке спецификатора производного класса.

  • Затем прямые базовые классы инициализируются в порядке объявления, поскольку они появляются в основном списке спецификатора (независимо от порядка инициализаторов мадам).

  • Затем нестатические элементы данных инициализируются в порядке, которым они были объявлены в определении класса (снова независимо от порядка инициализаторов мадам).

  • Наконец, составной оператор тела конструктора выполняется.


Главная причина для использования init-списков состоит в том, чтобы помочь компилятору с оптимизацией. Init-списки для неосновных типов (т.е. объекты класса, а не int, float, и т.д.), может обычно создаваться оперативный.

Если Вы создаете объект, затем присваивают ему в конструкторе, это обычно приводит к созданию и разрушению временных объектов, которое неэффективно.

Init-списки могут избежать этого (если компилятор до него, конечно, но большинство из них должно быть).

Следующая полная программа произведет 7, но это для определенного компилятора (CygWin g ++), таким образом, это не гарантирует что поведение больше, чем образец в исходном вопросе.

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

#include <iostream>
class Foo {
    int x;
    public:
        Foo(): x(7) {
            std::cout << x << std::endl;
        }
};
int main (void) {
    Foo foo;
    return 0;
}
20
ответ дан 1 December 2019 в 01:39
поделиться

Да, C++ создает всех участников прежде, чем назвать код constructur.

7
ответ дан 1 December 2019 в 01:39
поделиться

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

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

Возможно, что Вы перепутали то, что необходимо обратиться к параметрам а не к членским атрибутам в списке инициализации. Как пример, учитывая класс X, который имеет двух участников (a_ и b _) интервала типа, следующий конструктор может быть неточным:

 X::X( int a ) : a_( a ), b( a_*2 ) {}

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

class X
{
public:
   X( int a );
private:
   int b_;
   int a_; 
};

Затем независимо от того, как Вы вводите список инициализации, факт - то, что b _ (a_*2) будет выполняться, прежде чем a_ инициализируется, так как объявление участников является первым b_ и позже a_. Это создаст ошибку, как Ваш код полагает (и вероятно зависит) на b_, являющемся дважды значением _, и на самом деле b_ содержит мусор. Простое решение не относится к участникам:

 X::X( int a ) : a_( a ), b( a*2 ) {} // correct regardless of how X is declared

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

7
ответ дан 1 December 2019 в 01:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: