Batch-Apply Pillow Image Transforms, Then Parallelize: Processes vs Threads

Read the full interview experience this question came from →

Quick Overview

A Python coding exercise that applies a given sequence of Pillow transforms to a folder of cat images and then asks you to cut the total processing time. It tests clean per-image code, reasoning about CPU-bound work and the GIL, choosing between processes and threads, and sizing a worker pool.

Batch-Apply Pillow Image Transforms, Then Parallelize: Processes vs Threads

Company: Anthropic

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: hard

Interview Round: Onsite

You are given a set of cat images and must apply a series of image transforms to each one. The interviewer fixes the image library, Pillow, and the starter material shows how to call each required transform in Pillow. A provided test harness runs your code over all the images, checks the results, and reports how long it took to process all of them. For practice, treat the transforms as a fixed sequence of standard Pillow operations (for example a resize, a rotation and a grayscale conversion) applied in order to every image. In the interview, the exact list and the exact calls come from the starter material. ### Constraints and Clarifications - Use Pillow for all image work; the call for each transform is given. - A faster version must produce exactly the same output images as the simple version, because the tests check the results. - The number of images, their sizes and the number of CPU cores on the test machine are not given. Ask, or state your assumptions. ### Clarifying Questions - Is the same transform sequence applied to every image, or does each image have its own list? - Where should outputs be written, and how should they be named? May an output overwrite its input? - If one image is corrupt or cannot be opened, should the whole run fail, or should it continue and report the failure? - Roughly how many images are there, how large are they, and how many CPU cores does the test machine have? ### Part 1 — Apply the transforms Implement the processing: for every input image, open it, apply the transforms in order using the given Pillow calls, and save the result. Make the provided tests pass. ```hint Keep one image's work self-contained Write the work for a single image, from opening the file to saving the result, as one unit that shares no state with the others. Testing, error handling and Part 2 all become easier. ``` #### What This Part Should Cover - Correct use of the given Pillow calls in the required order, including image modes and formats on save - Resource handling: closing files and keeping only one image's data in memory at a time - A clean per-image unit of work and a driver over all inputs - Handling of unreadable or unusual images ### Part 2 — Make it faster The harness reports the total time. Reduce it. If you parallelize the work, be ready for two questions from the interviewer: - Why did you choose multiple processes rather than multiple threads, or the reverse? - If you use processes, how many workers do you start, and why that number? ```hint Find where the time goes Before choosing a tool, decide whether the per-image work is limited by the CPU or by waiting on the disk, and what that means for Python threads. ``` ```hint Sizing the pool Think about how many workers the machine can actually run at the same moment, and what each extra worker costs in start-up time and memory. ``` #### Clarifying Questions for this Part - Are all the cores the operating system reports available to this process, or is it limited, for example by a container CPU quota? - Does the reported time include starting the workers? #### What This Part Should Cover - Whether the workload is CPU-bound or I/O-bound, and how to check - The global interpreter lock and what it means for threads versus processes, including where Pillow does and does not release it - Reasoning for the worker count, confirmed by measurement - Overheads: process start-up, data sent between processes, batching of tasks, and memory per worker ### What a Strong Answer Covers - A correct, tested Part 1 before any optimization - A measured baseline and measured improvements - A parallel structure that sends paths rather than image data and produces identical outputs - An accurate explanation of the trade-off between processes and threads for this workload - Failure handling that still works in the parallel version ### Follow-up Questions - The image set grows to millions of files spread across many machines. What changes? - Profiling shows most of the time is spent decoding and encoding JPEG files. What would you try? - On an 8-core machine, 8 workers turn out slower than 6. What could explain it? - How would you make the run resumable if it crashes halfway through?

Overview: A Python coding exercise that applies a given sequence of Pillow transforms to a folder of cat images and then asks you to cut the total processing time. It tests clean per-image code, reasoning about CPU-bound work and the GIL, choosing between processes and threads, and sizing a worker pool.

Read the full Anthropic Software Engineer interview experience this question came from

|Home/Software Engineering Fundamentals/Anthropic
Anthropic logo
Anthropic
Jul 26, 2026
hardSoftware EngineerOnsiteSoftware Engineering Fundamentals
0
0

You are given a set of cat images and must apply a series of image transforms to each one. The interviewer fixes the image library, Pillow, and the starter material shows how to call each required transform in Pillow. A provided test harness runs your code over all the images, checks the results, and reports how long it took to process all of them.

For practice, treat the transforms as a fixed sequence of standard Pillow operations (for example a resize, a rotation and a grayscale conversion) applied in order to every image. In the interview, the exact list and the exact calls come from the starter material.

Constraints and Clarifications

  • Use Pillow for all image work; the call for each transform is given.
  • A faster version must produce exactly the same output images as the simple version, because the tests check the results.
  • The number of images, their sizes and the number of CPU cores on the test machine are not given. Ask, or state your assumptions.

Clarifying Questions Guidance

  • Is the same transform sequence applied to every image, or does each image have its own list?
  • Where should outputs be written, and how should they be named? May an output overwrite its input?
  • If one image is corrupt or cannot be opened, should the whole run fail, or should it continue and report the failure?
  • Roughly how many images are there, how large are they, and how many CPU cores does the test machine have?

Part 1 — Apply the transforms

Implement the processing: for every input image, open it, apply the transforms in order using the given Pillow calls, and save the result. Make the provided tests pass.

What This Part Should Cover Guidance

  • Correct use of the given Pillow calls in the required order, including image modes and formats on save
  • Resource handling: closing files and keeping only one image's data in memory at a time
  • A clean per-image unit of work and a driver over all inputs
  • Handling of unreadable or unusual images

Part 2 — Make it faster

The harness reports the total time. Reduce it. If you parallelize the work, be ready for two questions from the interviewer:

  • Why did you choose multiple processes rather than multiple threads, or the reverse?
  • If you use processes, how many workers do you start, and why that number?

Clarifying Questions for this Part Guidance

  • Are all the cores the operating system reports available to this process, or is it limited, for example by a container CPU quota?
  • Does the reported time include starting the workers?

What This Part Should Cover Guidance

  • Whether the workload is CPU-bound or I/O-bound, and how to check
  • The global interpreter lock and what it means for threads versus processes, including where Pillow does and does not release it
  • Reasoning for the worker count, confirmed by measurement
  • Overheads: process start-up, data sent between processes, batching of tasks, and memory per worker

What a Strong Answer Covers Guidance

  • A correct, tested Part 1 before any optimization
  • A measured baseline and measured improvements
  • A parallel structure that sends paths rather than image data and produces identical outputs
  • An accurate explanation of the trade-off between processes and threads for this workload
  • Failure handling that still works in the parallel version

Follow-up Questions Guidance

  • The image set grows to millions of files spread across many machines. What changes?
  • Profiling shows most of the time is spent decoding and encoding JPEG files. What would you try?
  • On an 8-core machine, 8 workers turn out slower than 6. What could explain it?
  • How would you make the run resumable if it crashes halfway through?
Loading comments...