We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Exception calling application: dictionary changed size during iteration
The exception occasionally happens when the worker reports gradients to ps.
![image](https://user-images.githubusercontent.com/18071380/76288063-d3925380-62e0-11ea-869f-64cccb4e7d37.png)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `elasticdl/python/ps/embedding_table.py`
Content:
```
1 import numpy as np
2 import tensorflow as tf
3 
4 from elasticdl.proto.elasticdl_pb2 import EmbeddingTableInfo
5 from elasticdl.python.common.dtypes import dtype_numpy_to_tensor
6 
7 
8 class EmbeddingTable(object):
9     """
10     EmbeddingTable is used to store embedding parameters of an embedding
11     layer. The name of an embedding table is actually the embedding layer
12     name. It uses a dictionary to store embedding vectors, the key is the
13     item id, the value is a 1-D numpy.ndarray.
14 
15     Embedding vectors are lazily initialized in parameter server.
16     EmbeddingTable also has dim and initializer fields. Inside the get
17     interface of EmbeddingTable, if the id is not in the embedding_vectors
18     dictionary, the corresponding value will be initialized.
19     """
20 
21     def __init__(self, name, dim=None, initializer=None, is_slot=False):
22         """
23         Args:
24             name: The embedding table name.
25             dim: The dimension of embeddings in this embedding table.
26             initializer: The initializer to initialize new embeddings. If this
27                 embedding table is for slots, `initializer` is a float and this
28                 table will initialize with constant initializer. Otherwise
29                 `initializer` is the name of Keras initializer.
30             is_slot: A bool. True for storing slot variable, otherwise false.
31         """
32         self.name = name
33         self.dim = dim
34         self.initializer_value = initializer
35         # set dtype to float32
36         self.dtype = np.dtype("float32")
37         if is_slot:
38             self.initializer = tf.keras.initializers.Constant(
39                 float(self.initializer_value)
40             )
41         else:
42             self.initializer = tf.keras.initializers.get(
43                 self.initializer_value
44             )
45         self.is_slot = is_slot
46         self.embedding_vectors = {}
47 
48     def get(self, indices):
49         if len(indices) == 0:
50             return None
51         values = []
52         for i in indices:
53             value = self.embedding_vectors.get(i, None)
54             if value is None:
55                 value = self.initializer(shape=(self.dim,)).numpy()
56                 self.embedding_vectors[i] = value
57             values.append(value)
58         return np.stack(values)
59 
60     def set(self, indices, values):
61         # TODO(qijun) need to add a RWLock in Sync-SGD
62         for index, i in enumerate(indices):
63             embedding_vector = values[index]
64             self.embedding_vectors[i] = embedding_vector
65 
66     def clear(self):
67         self.embedding_vectors.clear()
68 
69     def to_indexed_slices(self):
70         indices = []
71         embedding_vectors = []
72         for id, embedding_vector in self.embedding_vectors.items():
73             indices.append(id)
74             embedding_vectors.append(embedding_vector)
75         return tf.IndexedSlices(
76             values=np.array(embedding_vectors), indices=np.array(indices)
77         )
78 
79     def to_embedding_table_info_pb(self):
80         """Convert the embedding table information to a protobuf"""
81         embedding_pb = EmbeddingTableInfo()
82         embedding_pb.name = self.name
83         embedding_pb.dim = self.dim
84         embedding_pb.initializer = str(self.initializer_value)
85         embedding_pb.dtype = dtype_numpy_to_tensor(self.dtype)
86         return embedding_pb
87 
88     def get_table_size(self):
89         """Get the element count of an embedding table"""
90         if len(self.embedding_vectors) > 0:
91             element_size = list(self.embedding_vectors.values())[0].itemsize
92             size = self.dim * len(self.embedding_vectors) * element_size
93             return size
94         return 0
95 
96     def debug_info(self):
97         return (
98             "Embedding param name: %s\n  shape: [%d, %d]\n  size: %d bytes\n"
99             % (
100                 self.name,
101                 len(self.embedding_vectors),
102                 self.dim,
103                 self.get_table_size(),
104             )
105         )
106 
107 
108 # TODO(bug): create_embedding_table does not create EmbeddingTable correctly
109 #     if it is a slot table.
110 def create_embedding_table(embedding_table_info_pb):
111     name = embedding_table_info_pb.name
112     dim = embedding_table_info_pb.dim
113     initializer = embedding_table_info_pb.initializer
114     return EmbeddingTable(name, dim, initializer)
115 
116 
117 def get_slot_table_name(embedding_name, slot_name):
118     return embedding_name + "-" + slot_name
119
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/elasticdl/python/ps/embedding_table.py b/elasticdl/python/ps/embedding_table.py
--- a/elasticdl/python/ps/embedding_table.py
+++ b/elasticdl/python/ps/embedding_table.py
@@ -1,3 +1,5 @@
+import threading
+
 import numpy as np
 import tensorflow as tf
 
@@ -44,6 +46,7 @@
             )
         self.is_slot = is_slot
         self.embedding_vectors = {}
+        self._lock = threading.Lock()
 
     def get(self, indices):
         if len(indices) == 0:
@@ -52,8 +55,9 @@
         for i in indices:
             value = self.embedding_vectors.get(i, None)
             if value is None:
-                value = self.initializer(shape=(self.dim,)).numpy()
-                self.embedding_vectors[i] = value
+                with self._lock:
+                    value = self.initializer(shape=(self.dim,)).numpy()
+                    self.embedding_vectors[i] = value
             values.append(value)
         return np.stack(values)
 
@@ -69,9 +73,10 @@
     def to_indexed_slices(self):
         indices = []
         embedding_vectors = []
-        for id, embedding_vector in self.embedding_vectors.items():
-            indices.append(id)
-            embedding_vectors.append(embedding_vector)
+        with self._lock:
+            for id, embedding_vector in self.embedding_vectors.items():
+                indices.append(id)
+                embedding_vectors.append(embedding_vector)
         return tf.IndexedSlices(
             values=np.array(embedding_vectors), indices=np.array(indices)
         )

{"golden_diff": "diff --git a/elasticdl/python/ps/embedding_table.py b/elasticdl/python/ps/embedding_table.py\n--- a/elasticdl/python/ps/embedding_table.py\n+++ b/elasticdl/python/ps/embedding_table.py\n@@ -1,3 +1,5 @@\n+import threading\n+\n import numpy as np\n import tensorflow as tf\n \n@@ -44,6 +46,7 @@\n             )\n         self.is_slot = is_slot\n         self.embedding_vectors = {}\n+        self._lock = threading.Lock()\n \n     def get(self, indices):\n         if len(indices) == 0:\n@@ -52,8 +55,9 @@\n         for i in indices:\n             value = self.embedding_vectors.get(i, None)\n             if value is None:\n-                value = self.initializer(shape=(self.dim,)).numpy()\n-                self.embedding_vectors[i] = value\n+                with self._lock:\n+                    value = self.initializer(shape=(self.dim,)).numpy()\n+                    self.embedding_vectors[i] = value\n             values.append(value)\n         return np.stack(values)\n \n@@ -69,9 +73,10 @@\n     def to_indexed_slices(self):\n         indices = []\n         embedding_vectors = []\n-        for id, embedding_vector in self.embedding_vectors.items():\n-            indices.append(id)\n-            embedding_vectors.append(embedding_vector)\n+        with self._lock:\n+            for id, embedding_vector in self.embedding_vectors.items():\n+                indices.append(id)\n+                embedding_vectors.append(embedding_vector)\n         return tf.IndexedSlices(\n             values=np.array(embedding_vectors), indices=np.array(indices)\n         )\n", "issue": "Exception calling application: dictionary changed size during iteration\nThe exception occasionally happens when the worker reports gradients to ps.\r\n![image](https://user-images.githubusercontent.com/18071380/76288063-d3925380-62e0-11ea-869f-64cccb4e7d37.png)\r\n\n", "before_files": [{"content": "import numpy as np\nimport tensorflow as tf\n\nfrom elasticdl.proto.elasticdl_pb2 import EmbeddingTableInfo\nfrom elasticdl.python.common.dtypes import dtype_numpy_to_tensor\n\n\nclass EmbeddingTable(object):\n    \"\"\"\n    EmbeddingTable is used to store embedding parameters of an embedding\n    layer. The name of an embedding table is actually the embedding layer\n    name. It uses a dictionary to store embedding vectors, the key is the\n    item id, the value is a 1-D numpy.ndarray.\n\n    Embedding vectors are lazily initialized in parameter server.\n    EmbeddingTable also has dim and initializer fields. Inside the get\n    interface of EmbeddingTable, if the id is not in the embedding_vectors\n    dictionary, the corresponding value will be initialized.\n    \"\"\"\n\n    def __init__(self, name, dim=None, initializer=None, is_slot=False):\n        \"\"\"\n        Args:\n            name: The embedding table name.\n            dim: The dimension of embeddings in this embedding table.\n            initializer: The initializer to initialize new embeddings. If this\n                embedding table is for slots, `initializer` is a float and this\n                table will initialize with constant initializer. Otherwise\n                `initializer` is the name of Keras initializer.\n            is_slot: A bool. True for storing slot variable, otherwise false.\n        \"\"\"\n        self.name = name\n        self.dim = dim\n        self.initializer_value = initializer\n        # set dtype to float32\n        self.dtype = np.dtype(\"float32\")\n        if is_slot:\n            self.initializer = tf.keras.initializers.Constant(\n                float(self.initializer_value)\n            )\n        else:\n            self.initializer = tf.keras.initializers.get(\n                self.initializer_value\n            )\n        self.is_slot = is_slot\n        self.embedding_vectors = {}\n\n    def get(self, indices):\n        if len(indices) == 0:\n            return None\n        values = []\n        for i in indices:\n            value = self.embedding_vectors.get(i, None)\n            if value is None:\n                value = self.initializer(shape=(self.dim,)).numpy()\n                self.embedding_vectors[i] = value\n            values.append(value)\n        return np.stack(values)\n\n    def set(self, indices, values):\n        # TODO(qijun) need to add a RWLock in Sync-SGD\n        for index, i in enumerate(indices):\n            embedding_vector = values[index]\n            self.embedding_vectors[i] = embedding_vector\n\n    def clear(self):\n        self.embedding_vectors.clear()\n\n    def to_indexed_slices(self):\n        indices = []\n        embedding_vectors = []\n        for id, embedding_vector in self.embedding_vectors.items():\n            indices.append(id)\n            embedding_vectors.append(embedding_vector)\n        return tf.IndexedSlices(\n            values=np.array(embedding_vectors), indices=np.array(indices)\n        )\n\n    def to_embedding_table_info_pb(self):\n        \"\"\"Convert the embedding table information to a protobuf\"\"\"\n        embedding_pb = EmbeddingTableInfo()\n        embedding_pb.name = self.name\n        embedding_pb.dim = self.dim\n        embedding_pb.initializer = str(self.initializer_value)\n        embedding_pb.dtype = dtype_numpy_to_tensor(self.dtype)\n        return embedding_pb\n\n    def get_table_size(self):\n        \"\"\"Get the element count of an embedding table\"\"\"\n        if len(self.embedding_vectors) > 0:\n            element_size = list(self.embedding_vectors.values())[0].itemsize\n            size = self.dim * len(self.embedding_vectors) * element_size\n            return size\n        return 0\n\n    def debug_info(self):\n        return (\n            \"Embedding param name: %s\\n  shape: [%d, %d]\\n  size: %d bytes\\n\"\n            % (\n                self.name,\n                len(self.embedding_vectors),\n                self.dim,\n                self.get_table_size(),\n            )\n        )\n\n\n# TODO(bug): create_embedding_table does not create EmbeddingTable correctly\n#     if it is a slot table.\ndef create_embedding_table(embedding_table_info_pb):\n    name = embedding_table_info_pb.name\n    dim = embedding_table_info_pb.dim\n    initializer = embedding_table_info_pb.initializer\n    return EmbeddingTable(name, dim, initializer)\n\n\ndef get_slot_table_name(embedding_name, slot_name):\n    return embedding_name + \"-\" + slot_name\n", "path": "elasticdl/python/ps/embedding_table.py"}], "after_files": [{"content": "import threading\n\nimport numpy as np\nimport tensorflow as tf\n\nfrom elasticdl.proto.elasticdl_pb2 import EmbeddingTableInfo\nfrom elasticdl.python.common.dtypes import dtype_numpy_to_tensor\n\n\nclass EmbeddingTable(object):\n    \"\"\"\n    EmbeddingTable is used to store embedding parameters of an embedding\n    layer. The name of an embedding table is actually the embedding layer\n    name. It uses a dictionary to store embedding vectors, the key is the\n    item id, the value is a 1-D numpy.ndarray.\n\n    Embedding vectors are lazily initialized in parameter server.\n    EmbeddingTable also has dim and initializer fields. Inside the get\n    interface of EmbeddingTable, if the id is not in the embedding_vectors\n    dictionary, the corresponding value will be initialized.\n    \"\"\"\n\n    def __init__(self, name, dim=None, initializer=None, is_slot=False):\n        \"\"\"\n        Args:\n            name: The embedding table name.\n            dim: The dimension of embeddings in this embedding table.\n            initializer: The initializer to initialize new embeddings. If this\n                embedding table is for slots, `initializer` is a float and this\n                table will initialize with constant initializer. Otherwise\n                `initializer` is the name of Keras initializer.\n            is_slot: A bool. True for storing slot variable, otherwise false.\n        \"\"\"\n        self.name = name\n        self.dim = dim\n        self.initializer_value = initializer\n        # set dtype to float32\n        self.dtype = np.dtype(\"float32\")\n        if is_slot:\n            self.initializer = tf.keras.initializers.Constant(\n                float(self.initializer_value)\n            )\n        else:\n            self.initializer = tf.keras.initializers.get(\n                self.initializer_value\n            )\n        self.is_slot = is_slot\n        self.embedding_vectors = {}\n        self._lock = threading.Lock()\n\n    def get(self, indices):\n        if len(indices) == 0:\n            return None\n        values = []\n        for i in indices:\n            value = self.embedding_vectors.get(i, None)\n            if value is None:\n                with self._lock:\n                    value = self.initializer(shape=(self.dim,)).numpy()\n                    self.embedding_vectors[i] = value\n            values.append(value)\n        return np.stack(values)\n\n    def set(self, indices, values):\n        # TODO(qijun) need to add a RWLock in Sync-SGD\n        for index, i in enumerate(indices):\n            embedding_vector = values[index]\n            self.embedding_vectors[i] = embedding_vector\n\n    def clear(self):\n        self.embedding_vectors.clear()\n\n    def to_indexed_slices(self):\n        indices = []\n        embedding_vectors = []\n        with self._lock:\n            for id, embedding_vector in self.embedding_vectors.items():\n                indices.append(id)\n                embedding_vectors.append(embedding_vector)\n        return tf.IndexedSlices(\n            values=np.array(embedding_vectors), indices=np.array(indices)\n        )\n\n    def to_embedding_table_info_pb(self):\n        \"\"\"Convert the embedding table information to a protobuf\"\"\"\n        embedding_pb = EmbeddingTableInfo()\n        embedding_pb.name = self.name\n        embedding_pb.dim = self.dim\n        embedding_pb.initializer = str(self.initializer_value)\n        embedding_pb.dtype = dtype_numpy_to_tensor(self.dtype)\n        return embedding_pb\n\n    def get_table_size(self):\n        \"\"\"Get the element count of an embedding table\"\"\"\n        if len(self.embedding_vectors) > 0:\n            element_size = list(self.embedding_vectors.values())[0].itemsize\n            size = self.dim * len(self.embedding_vectors) * element_size\n            return size\n        return 0\n\n    def debug_info(self):\n        return (\n            \"Embedding param name: %s\\n  shape: [%d, %d]\\n  size: %d bytes\\n\"\n            % (\n                self.name,\n                len(self.embedding_vectors),\n                self.dim,\n                self.get_table_size(),\n            )\n        )\n\n\n# TODO(bug): create_embedding_table does not create EmbeddingTable correctly\n#     if it is a slot table.\ndef create_embedding_table(embedding_table_info_pb):\n    name = embedding_table_info_pb.name\n    dim = embedding_table_info_pb.dim\n    initializer = embedding_table_info_pb.initializer\n    return EmbeddingTable(name, dim, initializer)\n\n\ndef get_slot_table_name(embedding_name, slot_name):\n    return embedding_name + \"-\" + slot_name\n", "path": "elasticdl/python/ps/embedding_table.py"}]}