Repository: deepset-ai/haystack

Issue:
Fix multiprocessing sharing_strategy for Windows
**Describe the bug**

Our windows CI is failing after introducing a new "sharing_strategy" in  https://github.com/deepset-ai/haystack/pull/1928.
Seems like the default `file_descriptor` is not valid on Windows. 
See: https://github.com/deepset-ai/haystack/runs/4705444152?check_suite_focus=true

Potential fix: Let's detect if we are on windows and adjust the default value to a valid option.


**Error message**

```______________ test_table_text_retriever_training[elasticsearch] ______________

document_store = <haystack.document_stores.elasticsearch.ElasticsearchDocumentStore object at 0x00000199451F8808>

    @pytest.mark.vector_dim(128)
    def test_table_text_retriever_training(document_store):
        retriever = TableTextRetriever(
            document_store=document_store,
            query_embedding_model="prajjwal1/bert-tiny",
            passage_embedding_model="prajjwal1/bert-tiny",
            table_embedding_model="prajjwal1/bert-tiny",
            use_gpu=False
        )
    
        retriever.train(
            data_dir="samples/mmr",
            train_filename="sample.json",
            n_epochs=1,
            n_gpu=0,
>           save_dir="test_table_text_retriever_train"
        )

test_retriever.py:343: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\haystack\nodes\retriever\dense.py:861: in train
    max_processes=max_processes)
..\haystack\modeling\data_handler\data_silo.py:103: in __init__
    self._load_data()
..\haystack\modeling\data_handler\data_silo.py:221: in _load_data
    self.data["train"], self.tensor_names = self._get_dataset(train_file)
..\haystack\modeling\data_handler\data_silo.py:147: in _get_dataset
    mp.set_sharing_strategy(self.multiprocessing_strategy)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

new_strategy = 'file_descriptor'

    def set_sharing_strategy(new_strategy):
        """Sets the strategy for sharing CPU tensors.
    
        Args:
            new_strategy (str): Name of the selected strategy. Should be one of
                the values returned by :func:`get_all_sharing_strategies()`.
        """
        global _sharing_strategy
>       assert new_strategy in _all_sharing_strategies
E       AssertionError

c:\hostedtoolcache\windows\python\3.7.9\x64\lib\site-packages\torch\multiprocessing\__init__.py:58: AssertionError
```

**FAQ Check**
- [x] Have you had a look at [our new FAQ page](https://haystack.deepset.ai/overview/faq)?

**System:**
 - OS: Windows 
 - GPU/CPU: CPU multiprocessing
 - Haystack version (commit or version number): current master 




Discussion:

Resolving patch:
diff --git a/haystack/modeling/data_handler/data_silo.py b/haystack/modeling/data_handler/data_silo.py
--- a/haystack/modeling/data_handler/data_silo.py
+++ b/haystack/modeling/data_handler/data_silo.py
@@ -44,7 +44,7 @@ def __init__(
         automatic_loading: bool = True,
         max_multiprocessing_chunksize: int = 2000,
         max_processes: int = 128,
-        multiprocessing_strategy: str = 'file_descriptor',
+        multiprocessing_strategy: Optional[str] = None,
         caching: bool = False,
         cache_path: Path = Path("cache/data_silo"),
     ):
@@ -60,7 +60,7 @@ def __init__(
             values are rather large that might cause memory issues.
         :param max_processes: the maximum number of processes to spawn in the multiprocessing.Pool used in DataSilo.
                               It can be set to 1 to disable the use of multiprocessing or make debugging easier.
-        :multiprocessing_strategy: Set the multiprocessing sharing strategy, this can be one of file_descriptor/file_system.
+        :multiprocessing_strategy: Set the multiprocessing sharing strategy, this can be one of file_descriptor/file_system depending on your OS.
                                    If your system has low limits for the number of open file descriptors, and you can’t raise them,
                                    you should use the file_system strategy.
         :param caching: save the processed datasets on disk to save time/compute if the same train data is used to run
@@ -143,13 +143,14 @@ def _get_dataset(self, filename: Optional[Union[str, Path]], dicts: Optional[Lis
 
         with ExitStack() as stack:
             if self.max_processes > 1:  # use multiprocessing only when max_processes > 1
-                if self.multiprocessing_strategy and self.multiprocessing_strategy in ['file_descriptor', 'file_system']:
-                    mp.set_sharing_strategy(self.multiprocessing_strategy)
-                else:
-                    logger.warning(
-                        f"{self.multiprocessing_strategy} is an invalid strategy, "
-                        f"falling back to default (file_descriptor) strategy."
-                    )
+                if self.multiprocessing_strategy:
+                    if self.multiprocessing_strategy in mp.get_all_sharing_strategies():
+                        mp.set_sharing_strategy(self.multiprocessing_strategy)
+                    else:
+                        logger.warning(
+                            f"{self.multiprocessing_strategy} is unavailable, "
+                            f"falling back to default multiprocessing sharing strategy of your OS."
+                        )
 
                 p = stack.enter_context(mp.Pool(processes=num_cpus_used))
 
@@ -823,4 +824,4 @@ def _get_checksum(self):
             "data_silo_type": self.__class__.__name__,
         }
         checksum = get_dict_checksum(payload_dict)
-        return checksum
\ No newline at end of file
+        return checksum
diff --git a/haystack/nodes/retriever/dense.py b/haystack/nodes/retriever/dense.py
--- a/haystack/nodes/retriever/dense.py
+++ b/haystack/nodes/retriever/dense.py
@@ -308,7 +308,7 @@ def train(self,
               test_filename: str = None,
               max_samples: int = None,
               max_processes: int = 128,
-              multiprocessing_strategy: str = 'file_descriptor',
+              multiprocessing_strategy: Optional[str] = None,
               dev_split: float = 0,
               batch_size: int = 2,
               embed_title: bool = True,
@@ -338,7 +338,7 @@ def train(self,
         :param max_samples: maximum number of input samples to convert. Can be used for debugging a smaller dataset.
         :param max_processes: the maximum number of processes to spawn in the multiprocessing.Pool used in DataSilo.
                               It can be set to 1 to disable the use of multiprocessing or make debugging easier.
-        :param multiprocessing_strategy: Set the multiprocessing sharing strategy, this can be one of file_descriptor/file_system.
+        :param multiprocessing_strategy: Set the multiprocessing sharing strategy, this can be one of file_descriptor/file_system depending on your OS.
                                          If your system has low limits for the number of open file descriptors, and you can’t raise them,
                                          you should use the file_system strategy.
         :param dev_split: The proportion of the train set that will sliced. Only works if dev_filename is set to None


Test patch: