writing tfrecord with multithreading is not fast as expected
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Understanding TFRecord Files
TensorFlow's TFRecord format is widely used for storing large datasets in a compressed, efficient manner, which is both memory and performance-friendly. TFRecord files are binary files that efficiently store sequences of binary records. Despite their benefits, creating TFRecords, especially utilizing multithreading, can sometimes lead to performance bottlenecks or not provide the expected speed improvements.
Multithreading with Python
Python, due to its Global Interpreter Lock (GIL), can have some limitations when it comes to multithreading. The GIL is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes at once. This can be an impediment when aiming for speed through multithreading, as threads may often be waiting to acquire the GIL rather than executing meaningful work.
Writing TFRecords with Multithreading
Why Multithreading?
The main reasons to use multithreading when writing TFRecords:
- Increased Throughput: By dividing the tasks among several threads, the workload can be processed in parallel.
- Resource Utilization: Better use of CPU resources if one I/O-bound operation can run concurrently while another thread processes data.
However, in practice, the expected performance gains may not materialize.
Technical Explanation
- I/O Bound Operations: Writing TFRecords typically involves significant I/O operations. Disk I/O can become a significant bottleneck as all threads might end up waiting for disk operations to complete, leading to underutilization of CPU resources.
- GIL Constraints: Since Python's threads must acquire the GIL, CPU-bound operations do not execute in true parallel on multi-core processors. This results in negligible performance improvements for multithreaded TFRecord writing, especially if threads are predominantly CPU-bound once data is being handed off to the TFRecord writer.
- Serialization Overhead: Preparing datasets for TFRecords involves data serialization. This step, which includes converting raw data into binary format expected by the protocol buffer definitions, can be CPU intensive. The GIL further restricts parallel execution during this phase.
Example Scenario
Consider the scenario where we attempt to write TFRecord files using tf.data.Dataset API with multithreading. Here's a simplified example:
- Despite threading, the GIL prevents true parallel execution, especially inside the serialize and write operations.
- The I/O wait times increase due to simultaneous write requests.
Related reading
- You must feed a value for placeholder tensor 'Placeholder' with dtype float
- Your CPU supports instructions that this TensorFlow binary was not compiled to use AVX AVX2
- Your CPU supports instructions that this TensorFlow binary was not compiled to use AVX AVX2
- Zero initialiser for biases using get_variable in tensorflow
- Xcode 11 debugger is extremely slow - A known problem?
- Xcode 14 deprecates bitcode - but why?
- Writing to a TextBox from another thread?
- WSGI vs ASGI server with hybrid sync/async Django app

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.