<p>I happened upon an answer for this while looking at the library authors' paper: <a href="https://arxiv.org/abs/1710.11555" rel="nofollow noreferrer">https://arxiv.org/abs/1710.11555</a>.</p>
<p>In their paper they include an image of their distributed training environment and it notably includes a couple of parameterservers. <a href="https://i.stack.imgur.com/shJGx.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/shJGx.png" alt="distributed environment setup" /></a></p>
<p>The particular <code>merge_call</code> thing that tensorflow is complaining about in your question is something that I think has to be done on a separate device than the worker. So basically if you are trying to train the forest in a distributed setting, your runconfig has to look like</p>
<pre><code>strategy = tf.distribute.experimental.ParameterServerStrategy()
config = tf.estimator.RunConfig(
    train_distribute=strategy)
</code></pre>
<p>and you have to figure out how to set up TF_CONFIG appropriately so that the worker tensorflow process is aware of the chief and parameter servers. If you use google AI platform, they set that stuff up when you start the job. I haven't tried getting this to work locally or on a non-ai-platform cluster.</p>
Example for Distributed learning using tensorflow and boosted trees
<p>I have traversed through numerous githubs, however i am unable to find an example where Tensorflow distributed learning was used with Boosted Trees Classifier estimator. 
All the tutorials are for Neural nets. </p>

<p>I have slightly adapted the boosted trees code to work with distributed strategy as below: </p>

<pre><code>import numpy as np
import pandas as pd
from IPython.display import clear_output
from matplotlib import pyplot as plt
import tensorflow as tf
tf.random.set_seed(123)

dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv')
dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv')
y_train = dftrain.pop('survived')
y_eval = dfeval.pop('survived')

fc = tf.feature_column
CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

def one_hot_cat_column(feature_name, vocab):
  return tf.feature_column.indicator_column(
      tf.feature_column.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name,
                                           dtype=tf.float32))

NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(X), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).
    dataset = dataset.repeat(n_epochs)
    # In memory training doesn't use batching.
    dataset = dataset.batch(NUM_EXAMPLES)
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

n_batches = 10
mirrored_strategy = tf.distribute.MirroredStrategy()
config = tf.estimator.RunConfig(
    train_distribute=mirrored_strategy, eval_distribute=mirrored_strategy)
est = tf.estimator.BoostedTreesClassifier(feature_columns,
                                          n_batches_per_layer=n_batches,config=config)

  # The model will stop training once the specified number of trees is built, not
  # based on the number of steps.
est.train(train_input_fn, max_steps=100)

# Eval.
result = est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))


</code></pre>

<p>However, whenever i run this code, i get the error:</p>

<blockquote>
  <p><code>merge_call</code> called while defining a new graph or a tf.function. This can often happen if the function <code>fn</code> passed to <code>strategy.experimental_run()</code> is decorated with <code>@tf.function</code> (or contains a nested <code>@tf.function</code>), and <code>fn</code> contains a synchronization point, such as aggregating gradients. This behavior is not yet supported. Instead, please wrap the entire call <code>strategy.experimental_run(fn)</code> in a <code>@tf.function</code>, and avoid nested <code>tf.function</code>s that may potentially cross a synchronization boundary.</p>
</blockquote>

<p>So, i would be grateful if i could either get a way to debug this error or find an example which uses distributed learning with Boosted Trees.</p>