C vs Swift 1.2 and Getting Killed

When I started learning Swift, I revisited the Mandelbrot Set. It’s an old favorite of mine because it is so simple to compute some rather nice images.

Mandelbrot Set
Mandelbrot Set

The above image was computed using Swift with the vDSP library in the Accelerate Framework and Grand Central Dispatch. Keeping track of interior values allowed me to color the interior as well as the exterior.

Back in June of 2013, I wrote a very simple C program to compute the Mandelbrot Set and display it in a different way. It produced the following image.

Orbitals in C
Orbitals in C

The C code was very simple and single threaded. This is a run from the shell using the time utility.

Triton:Desktop david$ time ./Orbitals
Computing row 2880 of 2880
Done! Return code = 0

real	0m37.342s
user	0m37.202s
sys	0m0.090s

Each pixel in the set is iterated 4000 times. The complex values are mapped onto the complex plane with the upper left corner being (-2.0, 2.0) and the lower right corner being (2.0, -2.0). The image was originally generated in TARGA format using some code I scraped off the Internet. I converted it to PNG using Preview so that browsers can view it. For some reason, the code flips the image horizontally. I haven’t taken the trouble to debug it.

I also wanted to try a comparison of Swift to C for this computation. I should have gone for a pure transliteration so that I could get a valid speed comparison. But I didn’t. The Swift version does a few things the C version does not do. One is dynamic memory allocation for the computed values. Another is an abstraction of complex number arithmetic. The last is adding Grand Central Dispatch in an attempt to get more speed.

The dynamic memory allocation turned out to be a major performance killer.

Swift Memory Usage
Swift Memory Usage

The run time:

Triton:Desktop david$ time ./SwiftOrbitals
Done!

real	6m56.994s
user	5m17.282s
sys	4m56.695s

This computation produced the same image with the correct orientation. I used a Bitmap class I created to use QuartzCore instead of the TARGA code from the C version. Eventually I produced this image.

Orbitals in Swift
Orbitals in Swift

By the way, I recommend you download one of the two images to examine the detail. What you are seeing is the cumulative result of each point in the set as it is iterated. The values are mapped back to a bitmap for viewing.

I added the orbitals functionality to the same program that computed the above traditional view of the Mandelbrot Set. It uses vDSP and Grand Central Dispatch. Unfortunately, Something rather bad happens.

Triton:Desktop david$ time ./OrbitalsSwift
Killed: 9

real	6m16.576s
user	29m27.176s
sys	7m16.144s

No image is produced. The code does work for smaller images with fewer iterations. Running in the debugger is extremely time intensive. So I don’t know why it is getting killed. The debugger run looks like this.

Xcode 6.3β2 Running Orbitals Computation
Xcode 6.3β2 Running Orbitals Computation

The major take away on this is that Swift is not C or C++. For high performance computing, code has to be structured differently. Algorithmic analysis and profiling are critical, particularly when memory usage can become excessive. The C implementation has the advantage of running in constant space in spite of being a single threaded process. Using Grand Central Dispatch for threading is very easy. But it is no substitute for a bad algorithm.

You may download and play with the code used for these images from here. The code isn’t cleaned up and is certainly not production ready. There is also a dearth of comments. Sorry about that. I also assume the reader of the code is familiar with calculating the Mandelbrot Set.

Enjoy.

A Day In The Swift 1.2

Today I converted a small Swift 1.1 project to Swift 1.2. I did this with the very recently released 6.3β2 of Xcode. The convert function did a fair job. But I had to do some work by hand.   Most of it was very straight forward. But there is one member function that gave me some trouble. It was a tiny change that was required. See if you can spot it.

    func saveImage(path: String, type: String) {
        let image = createImage()
        let options: [String:AnyObject] = [kCGImagePropertyOrientation : 1, // top left
            kCGImagePropertyHasAlpha : true,
            kCGImageDestinationLossyCompressionQuality : 0.80]
        let url = NSURL.fileURLWithPath(path, isDirectory: false)
        var imageType = kUTTypePNG
        if type == "JPEG" {
            imageType = kUTTypeJPEG
        }
        let file = CGImageDestinationCreateWithURL(url, imageType, 1, nil)
        CGImageDestinationAddImage(file, image, options)
        CGImageDestinationFinalize(file)
    }
    func saveImage(path: String, type: String) {
        let image = createImage()
        let options: [NSString:AnyObject] = [kCGImagePropertyOrientation : 1, // top left
            kCGImagePropertyHasAlpha : true,
            kCGImageDestinationLossyCompressionQuality : 0.80]
        let url = NSURL.fileURLWithPath(path, isDirectory: false)
        var imageType = kUTTypePNG
        if type == "JPEG" {
            imageType = kUTTypeJPEG
        }
        let file = CGImageDestinationCreateWithURL(url, imageType, 1, nil)
        CGImageDestinationAddImage(file, image, options)
        CGImageDestinationFinalize(file)
    }

I do not at present (and may never will) have a proper user interface for this project. It’s part of my language learning process to leave out such things and concentrate on implementing the algorithm.

This does not prevent me from using the frameworks. As you can see by the code, I’m using the QuartzCore framework for producing an image from some source of data. That data is computed using both GCD and vDSP. The latter is in the Accelerate framework. The computation of the data keeps all the CPU cores quite busy. Proper use of GCD prevents the requirement for synchronization. I use different queues to do the work.

There is another computation I want to add to the code before I put it up on GitHub. When I’ve got that complete, I’ll post again on this topic. Meanwhile, as an enticement, I’ve got an image to share that is created by the code base I am working on.

Mandelbrot Set
Mandelbrot Set