# Parallelism - Understanding pmap and the batch\_size parameter

**URL:** <https://discourse.julialang.org/t/parallelism-understanding-pmap-and-the-batch-size-parameter/15604>\
**Category:** Julia at Scale\
**Created:** [September 28, 2018, 10:36am UTC](https://discourse.julialang.org/t/parallelism-understanding-pmap-and-the-batch-size-parameter/15604 "2018-09-28T10:36:47Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdsalerno](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mdsalerno/32/5539_2.png) [@mdsalerno](https://discourse.julialang.org/u/mdsalerno)\
**Post date:** [September 28, 2018, 10:36am UTC](https://discourse.julialang.org/t/parallelism-understanding-pmap-and-the-batch-size-parameter/15604/1 "2018-09-28T10:36:47Z")

</div>

I am running something that looks like the following:

```julia
addprocs(Sys.CPU_THREADS) 
pmap(x -> f(x, A, B, C), args)

```

I have 48 CPU cores and thus 48 workers after running addprocs. A, B, and C are DataFrames, the largest having approximate dimensions (2e6 x 8), and `f` performs a series of split-apply-combine operations over the DataFrames, paramaterized by `x`, and outputs a 1x4 array.

pmap provides a significant performance increase over the regular map, however, I do not fully understand how the batch\_size parameter affects execution and performance. On a sample of 500 inputs, my run-times scale with batch\_size as follows:

```julia
map(x -> f(x, A, B, C), args[1:500]) # ~176.8 seconds
pmap(x -> f(x, A, B, C), args[1:500], batch_size=1) # ~19.3 seconds
pmap(x -> f(x, A, B, C), args[1:500], batch_size=2) # ~10.1 seconds
pmap(x -> f(x, A, B, C), args[1:500], batch_size=10) # ~7.2 seconds
pmap(x -> f(x, A, B, C), args[1:500], batch_size=50) # ~6.5 seconds
pmap(x -> f(x, A, B, C), args[1:500], batch_size=100) # ~6.3 seconds
pmap(x -> f(x, A, B, C), args[1:500], batch_size=500) # ~6.4 seconds

```

What could potentially explain the increase in performance with increasing batch size? Is possibly due to a decrease in overhead from not having to broadcast the DataFrames to the workers as many times? Does the the fact that I’m seeing close to optimal performance with a batch\_size that’s equal to the input size suggest that I may be better off using multithreading?

The documentation for pmap briefly discusses batch\_size:

> pmap can also use a mix of processes and tasks via the batch\_size argument.  
> For batch sizes greater than 1, the collection is processed in multiple  
> batches, each of length batch\_size or less. A batch is sent as a single  
> request to a free worker, where a local asyncmap processes elements from the  
> batch using multiple concurrent tasks.

Does this mean that when I use batch\_size=500 for a 500-element input, all of the computation is being done by a single worker which manages asynchronous concurrent tasks/processes? Can finding the right batch\_size value be thought of as trying to strike the right balance between parallelism and concurrency subject to the size of the problem and the overhead limitations that result from spawning new processes and broadcasting the data?

I could also use some help understanding some of the process behavior I observed while testing. This first image displays my processes while I ran pmap with batch\_size=1.

 ![batch1](https://global.discourse-cdn.com/julialang/original/3X/4/b/4bdac7cdd9733729d74759095b041d594704dfc0.png)

This first image displays my processes while I ran pmap with batch\_size=500.

 ![batch500](https://global.discourse-cdn.com/julialang/original/3X/0/3/03d79081d8ec9250991e99d9018922294d34db60.png)

In the first image where batch\_size=1, we see that 10 of Julias 48 processes are running at the time of the screenshot, with the rest of the processes sleeping, and most processes utilizing less than 20% of their CPU capacity. In the second image, where batch\_size=500, almost all of the processes are running simultaneously, most at close to full CPU capacity. How do we explain the observed differences between these two cases?

---

<div class="post-metadata">

**Author:** ![Juan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juan/32/7657_2.png) [@Juan](https://discourse.julialang.org/u/Juan)\
**Post date:** [October 8, 2020, 3:22pm UTC](https://discourse.julialang.org/t/parallelism-understanding-pmap-and-the-batch-size-parameter/15604/2 "2020-10-08T15:22:12Z")

</div>

From here:

> **[Parallel computing](https://techytok.com/lesson-parallel-computing/)**
>
> From zero to Julia Lesson 16. Parallel computing

In the case where the time required to transfer data between processes is much longer than the computation time, it may be a good idea to set the batch\_size to a value greater than 1. In this one, each process will compute a batch of values before transferring the data.

As a rule of thumb, it is a good idea to set the batch size so that the computation time of a batch is at least 10 ms, this way most of the time will be spent on the computation of values and not on data transfer.  
In general, if the total computation will take less than 100 ms, there’s no need to use multi-processing.
