Skip to content

feat: Convergence criterion as a plan sequence (#18854) - #18854

Open
Yuhta wants to merge 1 commit into
facebookincubator:mainfrom
Yuhta:export-D118870175
Open

Yuhta wants to merge 1 commit into
facebookincubator:mainfrom
Yuhta:export-D118870175

Conversation

@Yuhta

@Yuhta Yuhta commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary:

X-link: facebookincubator/axiom#1834

PageRank's stopping rule is the RMSE of the per-vertex rank change, measured
after the update. That statistic does not exist until the body's last plan
has produced the new ranks -- and that plan's output is the state the
iteration commits, so the reduce that turns per-worker partials into one
verdict has nowhere to go inside the body.

Reducing it needs a shuffle of its own: each worker reduces its shard, the
partials exchange, one final aggregation emits the verdict. A Velox plan
fragment ends at a shuffle boundary, so that is not one plan but a chain of
them -- which a single ConvergenceConfig::plan cannot express.

ConvergenceConfig::plan becomes plans, chained exactly as
FixedPointNode::plans() are: the first starts with a StateSourceNode, every
later one starts with an Exchange, every non-last one ends with a
PartitionedOutput, and the last emits the single BOOLEAN verdict.
converging(plan, n) still takes one plan and delegates to the vector
overload, so existing callers are unchanged.

FixedPointNode validates that the chain really is that: exactly one incoming
shuffle per fragment, so a branching topology such as a distributed join is
rejected rather than silently half-checked on the primary input chain only;
matching schemas across each shuffle boundary; one partition count across every
stage, since taking the maximum does not make incompatible counts safe; and the
last plan's single BOOLEAN column. numWorkers() and requiresSplits()
account for the convergence chain because a convergence sequence that
reduces across workers needs coordinator-assigned peers just as a shuffling
body does: consult the body alone and a non-shuffling body with a shuffling
convergence chain reports one worker and no split requirement, leaving its
exchanges waiting on peers nobody assigned. Serialization round-trips the
chain.

Also adds ConvergenceConfig::whenDeltaEmpty(maxIterations), the semi-naive
termination test -- stop on the first iteration that writes no rows -- which
needs no convergence plan at all, and so no sub-task per iteration to recompute
a row count the framework already holds. Restricted to a non-shuffling fixed
point, because the delta is a worker's local shard.

Worker propagation through a nested fixed point is split into the next diff.

Plan-node half only; the execution that consumes it is at the top of the stack.

Differential Revision: D118870175

@netlify

netlify Bot commented Sep 4, 2026

Copy link
Copy Markdown

Deploy Preview for meta-velox canceled.

Name Link
🔨 Latest commit 18918d9
🔍 Latest deploy log https://app.netlify.com/projects/meta-velox/deploys/6aa4147855aadc000878a2a0

@meta-codesync

meta-codesync Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

@Yuhta has exported this pull request. If you are a Meta employee, you can view the originating Diff in D118870175.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Selective Build Plan

Linux release with adapters is running a selective build of 428 cmake targets (out of 621 total). See the CI workflows README for what this means.

Affected targets (428)

Directly changed (92)

Target Changed Files
materialized_partitioned_output_test FixedPointPlanNodes.h
spark_aggregation_fuzzer_test FixedPointPlanNodes.h
velox_aggregates_GeometryAggregateTest FixedPointPlanNodes.h
velox_aggregates_reduce_agg_bm FixedPointPlanNodes.h
velox_aggregates_simple_aggregates_bm FixedPointPlanNodes.h
velox_aggregates_string_keys_bm FixedPointPlanNodes.h
velox_aggregates_test_group0 FixedPointPlanNodes.h
velox_aggregates_test_group1 FixedPointPlanNodes.h
velox_aggregates_test_group2 FixedPointPlanNodes.h
velox_aggregates_test_group3 FixedPointPlanNodes.h
velox_aggregates_test_group4 FixedPointPlanNodes.h
velox_aggregation_fuzzer FixedPointPlanNodes.h
velox_aggregation_fuzzer_test FixedPointPlanNodes.h
velox_aggregation_result_verifier FixedPointPlanNodes.h
velox_core FixedPointPlanNodes.cpp, FixedPointPlanNodes.h
velox_core_test FixedPointPlanNodes.h, PlanNodeTest.cpp
velox_driver_test FixedPointPlanNodes.h
velox_dwio_parquet_table_scan_test FixedPointPlanNodes.h
velox_dwio_parquet_tpch_test FixedPointPlanNodes.h
velox_example_operator_extensibility FixedPointPlanNodes.h
velox_exchange_benchmark FixedPointPlanNodes.h
velox_exchange_fuzzer FixedPointPlanNodes.h
velox_exec_SpatialJoinTest FixedPointPlanNodes.h
velox_exec_bm_duplicate_project FixedPointPlanNodes.h
velox_exec_infra_test FixedPointPlanNodes.h
velox_exec_test_group0 FixedPointPlanNodes.h
velox_exec_test_group1 FixedPointPlanNodes.h
velox_exec_test_group2 FixedPointPlanNodes.h
velox_exec_test_group3 FixedPointPlanNodes.h
velox_exec_test_group4 FixedPointPlanNodes.h
velox_exec_test_group5 FixedPointPlanNodes.h
velox_exec_test_group6 FixedPointPlanNodes.h, PlanNodeSerdeTest.cpp
velox_exec_test_group7 FixedPointPlanNodes.h, PlanNodeToStringTest.cpp
velox_exec_test_group8 FixedPointPlanNodes.h
velox_exec_test_lib FixedPointPlanNodes.h
velox_exec_util_test_group0 FixedPointPlanNodes.h
velox_expression_test FixedPointPlanNodes.h
velox_filter_project_benchmark FixedPointPlanNodes.h
velox_functions_aggregates_test_lib FixedPointPlanNodes.h
velox_functions_spark_aggregates_test FixedPointPlanNodes.h
velox_functions_window_test_lib FixedPointPlanNodes.h
velox_fuzzer_connector_test FixedPointPlanNodes.h
velox_gcs_insert_test FixedPointPlanNodes.h
velox_gcs_multiendpoints_test FixedPointPlanNodes.h
velox_hash_join_build_benchmark FixedPointPlanNodes.h
velox_hash_join_left_benchmark FixedPointPlanNodes.h
velox_hash_join_right_semi_benchmark FixedPointPlanNodes.h
velox_hdfs_insert_test FixedPointPlanNodes.h
velox_hive_connector_test FixedPointPlanNodes.h
velox_hive_iceberg_equality_delete_test FixedPointPlanNodes.h
velox_hive_iceberg_insert_test FixedPointPlanNodes.h
velox_hive_iceberg_merge_sink_test FixedPointPlanNodes.h
velox_hive_iceberg_test FixedPointPlanNodes.h
velox_in_10_min_demo FixedPointPlanNodes.h
velox_join_fuzzer FixedPointPlanNodes.h
velox_key_encoder_test FixedPointPlanNodes.h
velox_mark_distinct_fuzzer_lib FixedPointPlanNodes.h
velox_mark_sorted_benchmark FixedPointPlanNodes.h
velox_memory_arbitration_fuzzer FixedPointPlanNodes.h
velox_memory_test FixedPointPlanNodes.h
velox_orderby_benchmark FixedPointPlanNodes.h
velox_parquet_writer_test FixedPointPlanNodes.h
velox_query_benchmark FixedPointPlanNodes.h
velox_query_trace_replayer_base FixedPointPlanNodes.h
velox_row_number_fuzzer_lib FixedPointPlanNodes.h
velox_rows_streaming_window_benchmark FixedPointPlanNodes.h
velox_rpc_aimd_under_load_test FixedPointPlanNodes.h
velox_rpc_operator_test FixedPointPlanNodes.h
velox_s3insert_test FixedPointPlanNodes.h
velox_s3multiendpoints_test FixedPointPlanNodes.h
velox_s3read_test FixedPointPlanNodes.h
velox_simple_aggregate_test FixedPointPlanNodes.h
velox_spark_query_runner_test FixedPointPlanNodes.h
velox_spark_windows_test FixedPointPlanNodes.h
velox_spatial_join_benchmark FixedPointPlanNodes.h
velox_spatial_join_fuzzer FixedPointPlanNodes.h
velox_streaming_aggregation_benchmark FixedPointPlanNodes.h
velox_table_evolution_fuzzer_test FixedPointPlanNodes.h
velox_tool_trace_test FixedPointPlanNodes.h
velox_topn_row_number_fuzzer_lib FixedPointPlanNodes.h
velox_tpcds_benchmark FixedPointPlanNodes.h
velox_tpcds_benchmark_lib FixedPointPlanNodes.h
velox_tpcds_connector_test FixedPointPlanNodes.h
velox_tpch_benchmark FixedPointPlanNodes.h
velox_tpch_benchmark_lib FixedPointPlanNodes.h
velox_tpch_connector_test FixedPointPlanNodes.h
velox_tpch_speed_test FixedPointPlanNodes.h
velox_window_fuzzer FixedPointPlanNodes.h
velox_window_fuzzer_test FixedPointPlanNodes.h
velox_window_prefixsort_benchmark FixedPointPlanNodes.h
velox_window_sub_partitioned_sort_benchmark FixedPointPlanNodes.h
velox_writer_fuzzer FixedPointPlanNodes.h

Transitively affected (336)

  • aggregate_companion_functions_test
  • materialized_output_buffer_test
  • physical_size_aggregator_test
  • presto_sql_test
  • spark_expression_fuzzer_test
  • velox_abfs
  • velox_abfs_registration_test
  • velox_abfs_test
  • velox_aggregates
  • velox_aggregation_fuzzer_base
  • velox_aggregation_runner_test
  • velox_arrow_bridge_test
  • velox_async_rpc_function_registry
  • velox_benchmark_array_writer_no_nulls
  • velox_benchmark_array_writer_with_nulls
  • velox_benchmark_basic_comparison_conjunct
  • velox_benchmark_basic_decoded_vector
  • velox_benchmark_basic_preproc
  • velox_benchmark_basic_selectivity_vector
  • velox_benchmark_basic_simple_arithmetic
  • velox_benchmark_basic_simple_cast
  • velox_benchmark_basic_vector_compare
  • velox_benchmark_basic_vector_fuzzer
  • velox_benchmark_basic_vector_slice
  • velox_benchmark_builder
  • velox_benchmark_estimate_flat_size
  • velox_benchmark_expr_flat_no_nulls
  • velox_benchmark_feature_normalization
  • velox_benchmark_local_remote_comparison
  • velox_benchmark_map_writer_no_nulls
  • velox_benchmark_map_writer_with_nulls
  • velox_benchmark_nested_array_writer_no_nulls
  • velox_benchmark_nested_array_writer_with_nulls
  • velox_cache_fuzzer
  • velox_cache_fuzzer_lib
  • velox_cast_benchmark
  • velox_common_compression_test
  • velox_common_geospatial_serde
  • velox_common_geospatial_serde_test
  • velox_common_test
  • velox_connector_registry
  • velox_connector_test
  • velox_constrained_input_generators
  • velox_constrained_input_generators_test
  • velox_constrained_vector_generator
  • velox_constrained_vector_generator_test
  • velox_core_plan_consistency_checker_test
  • velox_coverage_util
  • velox_cursor
  • velox_date_extract_benchmark
  • velox_demo_batch_rpc_function
  • velox_demo_rpc_function
  • velox_demo_rpc_function_test
  • velox_duckdb_conversion
  • velox_duckdb_conversion_test
  • velox_duckdb_parser
  • velox_dwio_arrow_parquet_writer
  • velox_dwio_arrow_parquet_writer_lib
  • velox_dwio_arrow_parquet_writer_test
  • velox_dwio_arrow_parquet_writer_test_lib
  • velox_dwio_arrow_parquet_writer_util_lib
  • velox_dwio_cache_test
  • velox_dwio_common
  • velox_dwio_common_bitpack_decoder_benchmark
  • velox_dwio_common_compression
  • velox_dwio_common_data_buffer_benchmark
  • velox_dwio_common_int_decoder_benchmark
  • velox_dwio_common_test
  • velox_dwio_common_test_utils
  • velox_dwio_dwrf_binary_stream_reader_test
  • velox_dwio_dwrf_buffered_output_stream_test
  • velox_dwio_dwrf_byte_rle_encoder_test
  • velox_dwio_dwrf_byte_rle_test
  • velox_dwio_dwrf_checksum_test
  • velox_dwio_dwrf_column_reader_test
  • velox_dwio_dwrf_column_statistics_test
  • velox_dwio_dwrf_common
  • velox_dwio_dwrf_compression_test
  • velox_dwio_dwrf_config_test
  • velox_dwio_dwrf_data_buffer_holder_test
  • velox_dwio_dwrf_decompression_test
  • velox_dwio_dwrf_decryption_test
  • velox_dwio_dwrf_dictionary_encoder_test
  • velox_dwio_dwrf_dictionary_encoding_utils_test
  • velox_dwio_dwrf_encoding_selector_test
  • velox_dwio_dwrf_encryption_test
  • velox_dwio_dwrf_flush_policy_test
  • velox_dwio_dwrf_index_builder_test
  • velox_dwio_dwrf_int_direct_test
  • velox_dwio_dwrf_int_encoder_test
  • velox_dwio_dwrf_layout_planner_test
  • velox_dwio_dwrf_ratio_checker_test
  • velox_dwio_dwrf_reader
  • velox_dwio_dwrf_reader_base_test
  • velox_dwio_dwrf_reader_test
  • velox_dwio_dwrf_rle_test
  • velox_dwio_dwrf_rlev1_encoder_test
  • velox_dwio_dwrf_stream_labels_test
  • velox_dwio_dwrf_stripe_dictionary_cache_test
  • velox_dwio_dwrf_stripe_reader_base_test
  • velox_dwio_dwrf_stripe_stream_test
  • velox_dwio_dwrf_utils
  • velox_dwio_dwrf_utils_test
  • velox_dwio_dwrf_writer
  • velox_dwio_dwrf_writer_context_test
  • velox_dwio_dwrf_writer_encoding_manager_test
  • velox_dwio_dwrf_writer_sink_test
  • velox_dwio_dwrf_writer_test
  • velox_dwio_faulty_file_sink
  • velox_dwio_iceberg_reader_benchmark
  • velox_dwio_iceberg_reader_benchmark_lib
  • velox_dwio_native_parquet_reader
  • velox_dwio_orc_column_statistics_test
  • velox_dwio_orc_reader
  • velox_dwio_orc_reader_filter_test
  • velox_dwio_orc_reader_test
  • velox_dwio_parquet_boolean_decoder_benchmark
  • velox_dwio_parquet_common
  • velox_dwio_parquet_common_test
  • velox_dwio_parquet_delta_bp_decoder_benchmark
  • velox_dwio_parquet_delta_bp_decoder_test
  • velox_dwio_parquet_metadata_benchmark
  • velox_dwio_parquet_page_reader_test
  • velox_dwio_parquet_reader
  • velox_dwio_parquet_reader_benchmark
  • velox_dwio_parquet_reader_benchmark_lib
  • velox_dwio_parquet_reader_test
  • velox_dwio_parquet_rlebp_decoder_test
  • velox_dwio_parquet_structure_decoder_benchmark
  • velox_dwio_parquet_structure_decoder_test
  • velox_dwio_parquet_test_base
  • velox_dwio_parquet_writer
  • velox_dwio_parquet_writer_benchmark
  • velox_dwio_text_reader
  • velox_dwio_text_reader_register
  • velox_dwio_text_writer
  • velox_dwio_text_writer_register
  • velox_dwrf_column_writer_index_test
  • velox_dwrf_column_writer_stats_test
  • velox_dwrf_column_writer_test
  • velox_dwrf_e2e_filter_test
  • velox_dwrf_e2e_reader_test
  • velox_dwrf_e2e_writer_test
  • velox_dwrf_float_column_writer_benchmark
  • velox_dwrf_int_encoder_benchmark
  • velox_dwrf_statistics_builder_utils_test
  • velox_dwrf_test_utils
  • velox_dwrf_writer_extended_test
  • velox_dwrf_writer_flush_test
  • velox_example_expression_eval
  • velox_example_opaque_type
  • velox_example_scan_orc
  • velox_example_simple_functions
  • velox_example_vector_reader_writer
  • velox_exec
  • velox_exec_prefixsort_test
  • velox_exec_vector_hasher_benchmark
  • velox_exec_window
  • velox_expression
  • velox_expression_fuzzer
  • velox_expression_fuzzer_test
  • velox_expression_fuzzer_test_utility
  • velox_expression_fuzzer_unit_test
  • velox_expression_runner
  • velox_expression_runner_test
  • velox_expression_runner_unit_test
  • velox_expression_test_utility
  • velox_expression_verifier
  • velox_expression_verifier_unit_test
  • velox_filemetadata_test
  • velox_format_datetime_benchmark
  • velox_function_dynamic_link_test
  • velox_function_registry
  • velox_function_registry_test
  • velox_functions_aggregates
  • velox_functions_aggregates_test
  • velox_functions_benchmarks_compare
  • velox_functions_benchmarks_row_writer_no_nulls
  • velox_functions_benchmarks_simdjson_function_with_expr
  • velox_functions_benchmarks_string_writer_no_nulls
  • velox_functions_benchmarks_url
  • velox_functions_geo
  • velox_functions_iceberg
  • velox_functions_iceberg_test
  • velox_functions_json
  • velox_functions_json_test
  • velox_functions_lib
  • velox_functions_lib_test
  • velox_functions_prestosql
  • velox_functions_prestosql_benchmarks_array_contains
  • velox_functions_prestosql_benchmarks_array_join
  • velox_functions_prestosql_benchmarks_array_min_max
  • velox_functions_prestosql_benchmarks_array_position
  • velox_functions_prestosql_benchmarks_array_sum
  • velox_functions_prestosql_benchmarks_bitwise
  • velox_functions_prestosql_benchmarks_cardinality
  • velox_functions_prestosql_benchmarks_comparisons
  • velox_functions_prestosql_benchmarks_concat
  • velox_functions_prestosql_benchmarks_date_time
  • velox_functions_prestosql_benchmarks_field_reference
  • velox_functions_prestosql_benchmarks_generic
  • velox_functions_prestosql_benchmarks_in
  • velox_functions_prestosql_benchmarks_map_concat
  • velox_functions_prestosql_benchmarks_map_except
  • velox_functions_prestosql_benchmarks_map_input
  • velox_functions_prestosql_benchmarks_map_intersect
  • velox_functions_prestosql_benchmarks_map_subscript
  • velox_functions_prestosql_benchmarks_map_zip_with
  • velox_functions_prestosql_benchmarks_not
  • velox_functions_prestosql_benchmarks_regexp_replace
  • velox_functions_prestosql_benchmarks_row
  • velox_functions_prestosql_benchmarks_string_ascii_utf_functions
  • velox_functions_prestosql_benchmarks_uuid_cast
  • velox_functions_prestosql_benchmarks_width_bucket
  • velox_functions_prestosql_benchmarks_zip
  • velox_functions_prestosql_benchmarks_zip_with
  • velox_functions_prestosql_impl
  • velox_functions_remote
  • velox_functions_remote_client_test
  • velox_functions_remote_server_main
  • velox_functions_spark
  • velox_functions_spark_aggregates
  • velox_functions_spark_impl
  • velox_functions_spark_specialforms
  • velox_functions_spark_test
  • velox_functions_spark_window
  • velox_functions_test
  • velox_functions_test_lib
  • velox_functions_window
  • velox_fuzzer_connector
  • velox_fuzzer_util
  • velox_gcs
  • velox_gcs_file_test
  • velox_gcsfile_example
  • velox_hash_benchmark
  • velox_hash_join_list_result_benchmark
  • velox_hash_join_prepare_join_table_benchmark
  • velox_hdfs
  • velox_hdfs_file_test
  • velox_hdfs_read_file_test
  • velox_hive_config
  • velox_hive_connector
  • velox_hive_iceberg_deletion_vector_test
  • velox_hive_iceberg_deletion_vector_writer_test
  • velox_hive_iceberg_merge_processor_test
  • velox_hive_iceberg_session_credentials_test
  • velox_hive_iceberg_splitreader
  • velox_hive_paimon_connector
  • velox_hive_paimon_data_file_meta_test
  • velox_hive_paimon_deletion_file_test
  • velox_hive_paimon_row_kind_test
  • velox_hive_paimon_split
  • velox_hive_paimon_split_test
  • velox_hive_partition_function
  • velox_hive_partition_function_benchmark
  • velox_hive_writer_options_adapter_test
  • velox_is_null_functions
  • velox_key_encoder
  • velox_like_benchmark
  • velox_like_tpch_benchmark
  • velox_mark_distinct_fuzzer
  • velox_merge_benchmark
  • velox_numeric_upcast_benchmark
  • velox_orderby_benchmark_util
  • velox_output_transport_registry_test
  • velox_parquet_e2e_filter_test
  • velox_parquet_writer_sink_test
  • velox_parse_expression
  • velox_parse_parser
  • velox_parse_test
  • velox_parse_utils
  • velox_prefixsort_benchmark
  • velox_presto_query_config
  • velox_presto_type_parser_test
  • velox_presto_types
  • velox_presto_types_fuzzer_utils
  • velox_presto_types_fuzzer_utils_test
  • velox_presto_types_test
  • velox_prestosql_coverage
  • velox_query_config_provider
  • velox_query_config_provider_test
  • velox_query_replayer
  • velox_re2_functions_benchmarks
  • velox_read_benchmark
  • velox_row_number_fuzzer
  • velox_row_serializer_benchmark
  • velox_row_test
  • velox_rpc_function_stubs
  • velox_rpc_node_test
  • velox_rpc_operator
  • velox_rpc_plan_node_translator
  • velox_s3config_test
  • velox_s3file_test
  • velox_s3finalize_test
  • velox_s3fs
  • velox_s3metrics_test
  • velox_s3registration_test
  • velox_serializer_benchmark
  • velox_serializer_test_group0
  • velox_simple_aggregate
  • velox_sort_benchmark
  • velox_spark_function_registry_test
  • velox_spark_query_config
  • velox_spark_query_runner
  • velox_sparksql_benchmarks_cast
  • velox_sparksql_benchmarks_compare
  • velox_sparksql_benchmarks_from_json
  • velox_sparksql_benchmarks_get_funcs
  • velox_sparksql_benchmarks_hash
  • velox_sparksql_benchmarks_in
  • velox_sparksql_benchmarks_simd_compare
  • velox_sparksql_benchmarks_split
  • velox_sparksql_coverage
  • velox_spill_fuzzer_base_lib
  • velox_spiller_aggregate_benchmark
  • velox_spiller_aggregate_benchmark_base
  • velox_spiller_join_benchmark
  • velox_spiller_join_benchmark_base
  • velox_test_util_test
  • velox_text_reader_test
  • velox_text_writer_test
  • velox_topn_row_number_fuzzer
  • velox_tpch_connector
  • velox_trace
  • velox_trace_file_tool
  • velox_trace_file_tool_base
  • velox_type_test
  • velox_unsafe_row_serialize_benchmark
  • velox_vector_fuzzer
  • velox_vector_fuzzer_test
  • velox_vector_test
  • velox_window
  • velox_windows_agg_test
  • velox_windows_rank_test
  • velox_windows_value_test
  • velox_writer_fuzzer_test

Fast path • Graph from main@0a0871f821f0

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

CI Failure Analysis

Auto-generated by the CI Failure Analysis workflow. This comment is updated in place each time CI fails on a new commit, so it always reflects the latest run — re-pushing or re-running CI will refresh the analysis below. Last updated 2026-09-04 22:23:22 UTC from workflow run 33924618921.

❌ Build with GCC / Linux release with adapters — BUILD Failure View logs

Build errors:

8 compilation errors in velox/core/tests/PlanNodeTest.cpp, all the same issue — -Werror=missing-field-initializers for ConvergenceConfig::plans:

velox/core/tests/PlanNodeTest.cpp:620:72: error: missing initializer for member
    'facebook::velox::core::ConvergenceConfig::plans' [-Werror=missing-field-initializers]
velox/core/tests/PlanNodeTest.cpp:658:72: error: (same)
velox/core/tests/PlanNodeTest.cpp:671:72: error: (same)
velox/core/tests/PlanNodeTest.cpp:683:71: error: (same)
velox/core/tests/PlanNodeTest.cpp:730:72: error: (same)
velox/core/tests/PlanNodeTest.cpp:753:72: error: (same)
velox/core/tests/PlanNodeTest.cpp:764:72: error: (same)
velox/core/tests/PlanNodeTest.cpp:786:72: error: (same)

Each error is on a ConvergenceConfig designated-initializer that specifies .maxIterations and .errorWhenMaxIterationReached but omits the new .plans field. GCC with -Werror=missing-field-initializers treats the omission as an error.


Correlation with PR changes:

This is directly caused by the PR. The PR renamed ConvergenceConfig::plan (a single PlanNodePtr) to ConvergenceConfig::plans (a std::vector<PlanNodePtr>) in FixedPointPlanNodes.h. The PR updated some usages in PlanNodeTest.cpp (lines 692, 706) but missed 8 other designated-initializer sites (lines 620, 658, 671, 683, 730, 753, 764, 786) where ConvergenceConfig is constructed without a convergence plan — these previously had no .plan field (defaulting to nullptr) and now need .plans = {} to satisfy -Werror=missing-field-initializers.

Known issues:

  • The last 3 runs on main all passed. This is not a pre-existing or flaky failure.

Recommended fix:

Add .plans = {}, to each of the 8 ConvergenceConfig{...} initializers in PlanNodeTest.cpp that omit it. For example, change:

ConvergenceConfig{
    .maxIterations = 0, .errorWhenMaxIterationReached = false},

to:

ConvergenceConfig{
    .plans = {},
    .maxIterations = 0,
    .errorWhenMaxIterationReached = false},

at lines 620, 658, 671, 683, 730, 753, 764, and 786.

Yuhta added a commit to Yuhta/axiom that referenced this pull request Sep 11, 2026
Summary:
X-link: facebookincubator/velox#18854


PageRank's stopping rule is the RMSE of the per-vertex rank change, measured
*after* the update.  That statistic does not exist until the body's last plan
has produced the new ranks -- and that plan's output *is* the state the
iteration commits, so the reduce that turns per-worker partials into one
verdict has nowhere to go inside the body.

Reducing it needs a shuffle of its own: each worker reduces its shard, the
partials exchange, one final aggregation emits the verdict.  A Velox plan
fragment ends at a shuffle boundary, so that is not one plan but a chain of
them -- which a single `ConvergenceConfig::plan` cannot express.

`ConvergenceConfig::plan` becomes `plans`, chained exactly as
`FixedPointNode::plans()` are: the first starts with a `StateSourceNode`, every
later one starts with an `Exchange`, every non-last one ends with a
`PartitionedOutput`, and the last emits the single BOOLEAN verdict.
`converging(plan, n)` still takes one plan and delegates to the vector
overload, so existing callers are unchanged.

`FixedPointNode` validates that the chain really is that: exactly one incoming
shuffle per fragment, so a branching topology such as a distributed join is
rejected rather than silently half-checked on the primary input chain only;
matching schemas across each shuffle boundary; one partition count across every
stage, since taking the maximum does not make incompatible counts safe; and the
last plan's single BOOLEAN column.  `numWorkers()` and `requiresSplits()`
account for the convergence chain because a convergence sequence that
reduces across workers needs coordinator-assigned peers just as a shuffling
body does: consult the body alone and a non-shuffling body with a shuffling
convergence chain reports one worker and no split requirement, leaving its
exchanges waiting on peers nobody assigned.  Serialization round-trips the
chain.

Also adds `ConvergenceConfig::whenDeltaEmpty(maxIterations)`, the semi-naive
termination test -- stop on the first iteration that writes no rows -- which
needs no convergence plan at all, and so no sub-task per iteration to recompute
a row count the framework already holds.  Restricted to a non-shuffling fixed
point, because the delta is a worker's local shard.

Worker propagation through a *nested* fixed point is split into the next diff.

Plan-node half only; the execution that consumes it is at the top of the stack.

Differential Revision: D118870175
Summary:

X-link: facebookincubator/axiom#1834

PageRank's stopping rule is the RMSE of the per-vertex rank change, measured
*after* the update.  That statistic does not exist until the body's last plan
has produced the new ranks -- and that plan's output *is* the state the
iteration commits, so the reduce that turns per-worker partials into one
verdict has nowhere to go inside the body.

Reducing it needs a shuffle of its own: each worker reduces its shard, the
partials exchange, one final aggregation emits the verdict.  A Velox plan
fragment ends at a shuffle boundary, so that is not one plan but a chain of
them -- which a single `ConvergenceConfig::plan` cannot express.

`ConvergenceConfig::plan` becomes `plans`, chained exactly as
`FixedPointNode::plans()` are: the first starts with a `StateSourceNode`, every
later one starts with an `Exchange`, every non-last one ends with a
`PartitionedOutput`, and the last emits the single BOOLEAN verdict.
`converging(plan, n)` still takes one plan and delegates to the vector
overload, so existing callers are unchanged.

`FixedPointNode` validates that the chain really is that: exactly one incoming
shuffle per fragment, so a branching topology such as a distributed join is
rejected rather than silently half-checked on the primary input chain only;
matching schemas across each shuffle boundary; one partition count across every
stage, since taking the maximum does not make incompatible counts safe; and the
last plan's single BOOLEAN column.  `numWorkers()` and `requiresSplits()`
account for the convergence chain because a convergence sequence that
reduces across workers needs coordinator-assigned peers just as a shuffling
body does: consult the body alone and a non-shuffling body with a shuffling
convergence chain reports one worker and no split requirement, leaving its
exchanges waiting on peers nobody assigned.  Serialization round-trips the
chain.

Also adds `ConvergenceConfig::whenDeltaEmpty(maxIterations)`, the semi-naive
termination test -- stop on the first iteration that writes no rows -- which
needs no convergence plan at all, and so no sub-task per iteration to recompute
a row count the framework already holds.  Restricted to a non-shuffling fixed
point, because the delta is a worker's local shard.

Worker propagation through a *nested* fixed point is split into the next diff.

Plan-node half only; the execution that consumes it is at the top of the stack.

Differential Revision: D118870175
@meta-codesync meta-codesync Bot changed the title feat: Convergence criterion as a plan sequence feat: Convergence criterion as a plan sequence (#18854) Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant