Ask HN: Any ideas on how to thumbnail 2M images?
Hi,
I'm a developer at the New York Public Library and we're currently evaluating ways to create derivatives (i.e. thumbnails) from a library of 2 million master images.
At 5 seconds an image using a tool like ImageMagick (which might be optimistic), it will take 115 machine days.
Any suggestions or tips to speed up the process?
Edit: Original images are scanned TIFFs, 25-30MB each.
42 comments
[ 3.8 ms ] story [ 119 ms ] threadAlso, if you can parallelize it, it won't take 115 days.
Yes, definitely planning to parallelize but we're likely limited to four simultaneous instances so that will still take ~20-30 days.
Also, converting the (hi-res) images to JPEG before further processing may make the data somewhat easier to deal with. 25-30MB per image * 2 million would be 50-60 terabytes of data? Plus, how often would someone really benefit from having access to a 25-30MB TIFF vs a much smaller JPEG version in the same resolution? That alone could be reason to start with JPEG compression first.
I suggest actually timing some of this stuff before writing off the idea. If an image can be processed in 1 second, and you can parallelize it to 4 cores, some quick and dirty (and probably useless) math says 2 million images could be done in just under 6 days. I don't think that's too shabby for 2 million images.
Can you borrow some servers from a local computer store for a few weeks? It's not outside the realm of possibility. Call them all, they can only say "no". Or maybe some businesses in the area might have some spare resources. I'd say leverage your status as a pro bono organization for some goodwill help.
Parallelization is the way to go for a task like this.
Did you see this also: http://www.graphicsmagick.org/index.html
They claim to be faster than ImageMagic.
http://freeimage.sourceforge.net/
https://github.com/jcupitt/ruby-vips
NYT: http://open.blogs.nytimes.com/2007/11/01/self-service-prorat... and http://open.blogs.nytimes.com/2008/05/21/the-new-york-times-...
AWS Import/Export: http://aws.amazon.com/importexport/
That said, even serially 5 seconds per image seems very slow. Are you sure you're not hitting network latency from a remote filesystem or something? If so do some bulk copies to get the data locally then work on the local copy.
This is a linear time (O(n)) problem with a large set, so it's worth the effort to shave a few milliseconds where you can as each millisecond optimized will be multiplied 2-million-fold (about 35 minutes). Once you have an optimal configuration for single images, test a small set, then let it loose on the whole set. If you can shave off 2 seconds for a single image, that's 46 machine days right there.
Can you buffer the images onto a ramdisk during conversion? Guessing HDD IO will be a large bottleneck.
Be sure to run your single image test on different images, so you don't get false optimization positives due to various I/O caches.
What's the maximum number of images that ImageMagick will take in as a batch list? (Guessing it's somewhat short of 2M) Whatever it is, make sure to run as large a list as possible. There's a suggestion at http://www.imagemagick.org/Usage/files/#image_streams but it re-initializes IM each time which sounds slow (still, can put the binaries on a ramdisk?)
You want to create a stream / "tape head" type setup where files are being processed with minimum need to re-init the conversion program. But it looks like IM6 doesn't support this so, with a sampleset of that size, you may even want to look into coding up a simple C program using libtiff/libjpeg that's sole job is to run the conversion as a stream, if you have access to such skills. It may be faster than a large general purpose tool.
Simple parallelism - create the list, split it into N (ImagickMaxNum) input list files, run on N workstations to reduce the total problem time by O/N. True parallelism (network queue-based) may be worth exploring using a queue system (RabbitMQ?) but don't try to write it yourself.
There may be situations where it makes sense to access the files via a filename mask if you can rename them (img_0 -> img_2000000) so you don't have to store and parse the file list and can use a simple increment counter.
Hope this helps! I'm no optimization guru and the above is very top-of-mind, but I enjoy these large problem sets. I'm also in NYC, would love to help out the NYPL and would volunteer some free time to do so (I need a useful side project). PM me if you'd like to talk further!
EDIT: Is this the wrong problem to tackle entirely? Can you convert the set on demand and cache-as-you-go? ie. if it's book covers that people are browsing, the first user may wait 5 seconds for an image, but that's not awful... Is there a particular reason to want to create precached derivatives?
You probably want to move these images to AWS S3 and run compute jobs and upload the resulting images back up to S3. You could create AWS Simple Queue Messages with the S3 URLs of each of the images and pop messages and autoscale EC2 instances based on the depth of that queue. What's the plan for these files after they're processed?
I am local, have deep AWS experience and have next week off if you'd like some pro bono advice.
50TB S3 ~$1500/month SQS ~$0.50/million messages
1) I downloaded a 49.6 MB TIFF file from here: http://hubblesite.org/newscenter/archive/releases/2004/32/im...
2) From the OSX terminal:
$ time sips -Z 150 hs-2004-32-d-full_tif.tif
Resulting file size is 150x150px and 32KB.
Time to run process: 1.48s user 0.15s system 98% cpu 1.663 total
The superpower computer required for this incredible speed is a 3 year old MacBook Pro (with SSD) ;-)
UPDATE:
I created 10 copies of the image. Total size: 520.1 MB
$ time sips -Z 150 .tif
Time to process 10 images: 14.98s user 1.44s system 94% cpu 17.384 total (approximately 1.498 per image).
2000000 images 1.663 seconds = 38 days.
Note: This is using larger images (49.6MB vs the 25-30MB images you have) and is using a single MacBook Pro. Divide amongst a few machines and be done in a week. GraphicsMagick could possibly be even faster.
ANOTHER UPDATE:
Since your files are smaller (20-30MB), I found a 30MB jpg sample here: http://sto-rvlt-01.sys.comcast.net/speedtest/random4000x4000...
Time to process was much faster: 0.37s user 0.04s system 97% cpu 0.418 total
2000000 images * 0.418 seconds = 9.67 days
At that speed we are talking under 10 days. On a single 3 year old MacBook Pro. Using built-in software. Without any optimizations. Find 5 computers in the NY Public Library and you'll be done in 2 days.
I am not saying this is the fastest solution. I posted this because it appears that people are over-engineering this problem or proposing solutions which will cost a lot of money (Amazon, bandwidth, shipping hard drive fees, etc).
If you build out the skill set and scripts to run this type of job, you can process the images, store them on S3 and kill the running infrastructure. You can then run this process for big and small workloads as the needs arise on demand without having to own servers or space in a data center.
I suspect it's mostly the quality of the access points and less the efficiency of the algorithm making thumbnails.
I suspect that the secondary optimization is how quickly those access points become available. In the 17 hours between the time your question was posted and this comment, more than 12,000 images could have been thumbnailed and possibly 12,000 additional resources made available or meta-data records improved.
The great thing about starting with something slow that works is that there is plenty of time to improve it [and plenty of time to decide if it really needs improving].
If the process had started at 8am yesterday, more than 50,000 images would have been converted by 8am Monday morning.
Now in the real world of bureaucracy, there can be more friction entailed in obtaining a box, sticking it in the corner, and letting it run for four months, than spending substantial human time researching and implementing a solution that looks clever and elegant. But really, the hardware for this job, even if purchased new is only a few hundred dollars.