1

I am writing a program in Clojure that takes input from a text file 10000.txt (this has 10k, unsigned integers.) I then pass that list into my merge sort functions (a sigle thread, 2,4,8,16,32 threads).

When I run the program, by typing "clojure test.clj" it outputs the elapsed time of each of the functions, but the program does not terminate.

It hangs there like it is waiting for input or about to output something else. And then after about 1 minute the program finally terminates. There must be something going on behind the scenes. Any ideas on what it is/what I need to do to terminate the program after the input?

Output of the program (before termination) This is where it hangs for about 1 minute

Terminal Output Picture

(use 'clojure.java.io)
(require '[clojure.string :as str])

;Read file and store into numbers, as a string
(def numbers (slurp "10000.txt"))

;Parse the string 'numbers', ignore the spaces 
;and save the result into x1 (a lazy-seq of integers)
(def x1 (map #(Integer/parseInt %) (str/split numbers #"\s+")))

;Function that performs the operation of merge sort algorithm
(defn merge-lists [left right]
  (loop [head [] L left R right]
    (if (empty? L) (concat head R)
        (if (empty? R) (concat head L)
            (if (> (first L) (first R))
              (recur (conj head (first R)) L (rest R))
              (recur (conj head (first L)) (rest L) R))))))

;The other merge-sort functions use pmap to run merge sort in parallel
;Using 1,2,4,8,16,32 threads
(defn naive-merge-sort [list]
  (if (< (count list) 2) list
      (apply merge-lists
             (map naive-merge-sort
                  (split-at (/ (count list) 2) list)))))

(defn parallel-merge-sort-2 [list]
  (if (< (count list) 2) list
      (apply merge-lists
             (pmap naive-merge-sort
                   (split-at (/ (count list) 2) list)))))

(defn parallel-merge-sort-4 [list]
  (if (< (count list) 2) list
      (apply merge-lists
             (pmap parallel-merge-sort-2
                   (split-at (/ (count list) 2) list)))))

(defn parallel-merge-sort-8 [list]
  (if (< (count list) 2) list
      (apply merge-lists
             (pmap parallel-merge-sort-4
                   (split-at (/ (count list) 2) list)))))

(defn parallel-merge-sort-16 [list]
  (if (< (count list) 2) list
      (apply merge-lists
             (pmap parallel-merge-sort-8
                   (split-at (/ (count list) 2) list)))))

(defn parallel-merge-sort-32 [list]
  (if (< (count list) 2) list
      (apply merge-lists
             (pmap parallel-merge-sort-16
                   (split-at (/ (count list) 2) list)))))

;Run each of the merge-sort functions and output their time
(time (naive-merge-sort x1))
(time (parallel-merge-sort-2 x1))
(time (parallel-merge-sort-4 x1))
(time (parallel-merge-sort-8 x1))
(time (parallel-merge-sort-16 x1))
(time (parallel-merge-sort-32 x1))

Here is my 10000.txt file: https://pastebin.com/5vKXUk1u

My expected results would be for the program to terminate after the final time is printed, not taking 1 minute to terminate.

Thank you everyone for your time and help on this!

Spencer Apel
  • 31
  • 2
  • 11
  • 2
    Possible duplicate of [Why does Clojure hang after having performed my calculations?](https://stackoverflow.com/questions/2622750/why-does-clojure-hang-after-having-performed-my-calculations) – glts Apr 22 '19 at 06:46

1 Answers1

8

You need to call shutdown-agents at the end to stop Clojure's thread pool.

Also see Agents and Asynchronous Actions on clojure.org:

Note that use of Agents starts a pool of non-daemon background threads that will prevent shutdown of the JVM. Use shutdown-agents to terminate these threads and allow shutdown.

Taylor Wood
  • 15,886
  • 1
  • 20
  • 37
  • Thak you very much for this! This was my first program in Clojure and had no clue about it. This answer fixed my issue – Spencer Apel Apr 22 '19 at 02:39