How to Parallelize gRPC Calls in Python

Updated Sep 22, 2026

Environment

Driver

  • NI-Digital Pattern Driver

Programming Language

  • Python

In applications where test time is important, it is often necessary to use multi-threading to have as many operations execute in parallel as possible. However, the default behavior in many gRPC calls is to execute operations in series, which can lengthen test times.

This article will explain how to parallelize gRPC calls using ThreadPoolExecutor in Python.

To improve execution time when calling repeated-capability methods over gRPC in Python, you can use worker threads to execute the calls concurrently instead of iterating over each call sequentially.

One example of this is the 'fetch_history_ram_cycle_information' method in the nidigital Python module. Ordinarily when fetching multiple records, the method iterates over each record one at a time in sequence by calling self._fetch_sample for each record) and then waiting to start record n+1 until record n is fully fetched.

To work around this, you can use ThreadPoolExecutor to have each record run on its own worker thread. For example:

 

sample_indexes = range(position, position + samples_to_read)
with ThreadPoolExecutor(max_workers=self._max_workers) as executor:
    # map preserves input order, so records stay in sample order.
    samples = list(
        executor.map(
            lambda index: self._fetch_sample(site, pin_list, index),

                        sample_indexes,
        )
    )

 

This is just one example; this could potentially work in other situations where calls are truly independent and latency becomes a concern when executing sequential calls.

Using this procedure, execution time is greatly reduced. Using the above example of fetching History RAM cycle information, fetching 100 records serially takes 32.9 seconds. Using ThreadPoolExecutor with _max_workers = 64 (which spawns 64 parallel threds), execution time is 1.1 seconds.