0

I have applied the simulated annealing algorithm (in Java) to a personal project that I am working on, but was wondering if the SA algorithm would perform slightly better on the same dataset if written in another language (i.e. C++, Python, etc).

The dummy dataset that I have created consists of five thousand users' names, postcodes and dates of birth.

The SA algorithm is applied to the dataset in order to extract many different pieces of information.

At present, my most recent test is attempting to get the SA algorithm to detect all users whose birth dates fall within one week of each other (in any given year). Now, the SA algorithm works very well indeed; however, as I am a perfectionist, I would like to achieve slightly faster results and want to know if anybody has had any good experiences with SA producing excellent results on a similar-sized dataset, but written in other languages?

At the moment, the SA algorithm takes just under five seconds to perform a successful search.

Mus
  • 7,290
  • 24
  • 86
  • 130
  • Wouldn't it be faster to use a classical algorithm for that? SA is cool, but I don't really see why you need it for that usage. – harold May 01 '12 at 09:14
  • 1
    @harold: surely you mean 'SA is cooling' ? – High Performance Mark May 01 '12 at 09:14
  • 1
    I am not familiar with that algorithm, but 15 seconds for a data set of 5,000 objects seems **very** long. – assylias May 01 '12 at 09:15
  • 1
    Performance issues are almost always the result of the way you've approached the problem, not the language you've used. Unless you're specifically interesting in experimenting with another language for its own sake then I'd break out the profiler and see where your solution is spending its time. – Paolo May 01 '12 at 09:16
  • Fifteen seconds is ridiculously long for the problem you have stated. It is not an NP problem, it's just sorting and partitioning, so O(nlogn) or similar. – Marko Topolnik May 01 '12 at 09:19
  • Sorry, my mistake! I meant to write "five" seconds and wrote "fifteen" for some reason - I'm still half-asleep! I will update now. Thanks. – Mus May 01 '12 at 09:21
  • You should take less than 100ms on this problem with a proper algorithm. – Paweł Obrok May 01 '12 at 09:23
  • I agree; however, for this project I wanted to strictly use SA to see how fast I could get it down to due to the successful accuracy levels usually associated with SA. – Mus May 01 '12 at 09:25
  • @Paolo Thank you for your comment. I am specifically looking to use SA but, moreso, am looking to see if the implementation in a different language can yield slightly better results. – Mus May 01 '12 at 09:26
  • You shouldn't rewrite in another language until you have more information. I'd profile your app to see where the time is being spent. Maybe you just coded it badly. – duffymo May 01 '12 at 09:30
  • Thank you all, but there appears to be some misunderstanding. With regards to performance, whether it's five seconds, one minute, one nanosecond - it doesn't matter to me at this particular moment as my main aim is to see if the SA could potentially work better in another language. – Mus May 01 '12 at 09:33
  • I'm sure that you can find good and bad experiences at rewriting anything. Why must you come here and ask for permission to rewrite? Please do, and report back on your findings. – duffymo May 01 '12 at 09:36
  • I'm not "asking permission to rewrite". If you read my question it clearly asks if anybody here has used SA (in a language other than Java) on a similar-sized dataset and whether or not the performance was slightly better or worse. Have you done this, duffymo? – Mus May 01 '12 at 09:39
  • Well just looking at it as a "language benchmark", C++ is probably going to be slightly faster (especially Intel's compiler), Fortran may be faster yet (especially Intel's compiler), and if you're good enough at it Assembly will be even faster (but that's a pretty big if, beating ICC is hard). – harold May 01 '12 at 09:52
  • @user1366769 My point is you could write a slow SA algorithm in any language, if you want to make it faster find out whether it's your algorithm or the language itself that's holding you back – Paolo May 01 '12 at 09:55
  • I completely understand, but it seems that you do not quite follow my aim. Even if it does not seem to make sense to YOU, it is still my aim nevertheless and my aim is to see if using another language to program SA could yield slightly faster results. – Mus May 01 '12 at 10:00
  • To come back to SA. It's performance essentially depends on how you calculate energy, transition probability and cooling. I also think your performance is poor. So quite likely in one of these factors is room for improvement. Can you show your solution? – bdecaf May 01 '12 at 10:37
  • I think one can write a program that performs slightly better than yours in most any language, even in Python or Ruby -- and it's not going to be anything specific to that language, just better coding. That's the point everyone else here is trying to make. – Marko Topolnik May 01 '12 at 11:35
  • But, once again, my AIM has been overlooked. I am not looking for the OPTIMAL time - I am merely looking to see if it could POTENTIALLY be improved if written in another language. Anyhow, this question is now resolved and thus does not warrant any further comments. Thank you all for your assistance. – Mus May 01 '12 at 11:44

1 Answers1

3

I would write it in Java

public class UserSearchMain {
    static class Person {
        int id;
        int dateOfBirth;

        static Person[] generatePeople(int num) {
            Random rand = new Random();
            Person[] people = new Person[num];
            for (int i = 0; i < num; i++) {
                Person p = new Person();
                p.id = i;
                p.dateOfBirth = rand.nextInt(80 * 365); // any day for 80 years.
                people[i] = p;
            }
            return people;
        }
    }

    public static void main(String... args) {
        Person[] people = Person.generatePeople(5000);
        List<List<Person>> peopleByDOB = new ArrayList<List<Person>>();
        for (Person person : people) {
            int dob = person.dateOfBirth;
            while (peopleByDOB.size() <= dob) peopleByDOB.add(new ArrayList<Person>());
            peopleByDOB.get(dob).add(person);
        }

        Random rand = new Random();

        int warmup = 12 * 1000;
        int runs = 1000 * 1000;
        long start = 0;

        for (int i = -warmup; i < runs; i++) {
            if (i == 0) start = System.nanoTime();
            int dayToSearch = rand.nextInt(80 * 365);
            for (int j = Math.max(0, dayToSearch - 7); j <= dayToSearch + 7 && j < peopleByDOB.size(); j++) {
                List<Person> peopleWithCloseDOM = peopleByDOB.get(j);
            }
        }
        long time = System.nanoTime() - start;
        System.out.printf("Each search took an average of %,d ns%n", time / runs);
    }
}

prints

Each search took an average of 85 ns

Often the algorithim you use is more important than the choice of language.

EDIT: In answer to your original question, could you make this faster in C++ with the same algorithim? I would guess yes, but not by alot.


To speed it up further you could use multiple threads.

public static void main(String... args) throws ExecutionException, InterruptedException {
    Person[] people = Person.generatePeople(5000);
    final List<List<Person>> peopleByDOB = new ArrayList<List<Person>>();
    for (Person person : people) {
        int dob = person.dateOfBirth;
        while (peopleByDOB.size() <= dob) peopleByDOB.add(new ArrayList<Person>());
        peopleByDOB.get(dob).add(person);
    }

    final int runs = 10 * 1000 * 1000;
    long start = System.nanoTime();

    int processors = Runtime.getRuntime().availableProcessors();
    ExecutorService service = Executors.newFixedThreadPool(processors);
    List<Future> futures = new ArrayList<Future>();
    for (int i = 0; i < processors; i++) {
        futures.add(service.submit(new Runnable() {
            @Override
            public void run() {
                Random rand = new Random();
                for (int i = 0; i < runs; i++) {
                    int dayToSearch = rand.nextInt(80 * 365);
                    for (int j = Math.max(0, dayToSearch - 7); j <= dayToSearch + 7 && j < peopleByDOB.size(); j++) {
                        List<Person> peopleWithCloseDOM = peopleByDOB.get(j);
                    }
                }
            }
        }));
    }
    for (Future future : futures) {
        future.get();
    }
    service.shutdown();
    double timeSec = (System.nanoTime() - start) / 1e9;
    double rate = processors * runs / timeSec / 1e6;
    System.out.printf("The search throughput was %.1f million per second%n", rate);
}

prints

The search throughput was 32.4 million per second

which implies an average of about 31 ns per search.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Maybe I'm not seeing it. Can you point out where in your code you do the SA? – bdecaf May 01 '12 at 10:24
  • It solves the problem as stated. Its find all the people who have a date of birth within seven days of a date chosen at random. The point being to use the optimal solution for the problem you have. If its just an acedemic exercise, don't worry about performance and solve the people the way you want. – Peter Lawrey May 01 '12 at 10:30
  • It isn't an academic exercise - it is just something that I am developing for my own purposes and was curious to see if another language would yield even slightly better results. Thanks again. – Mus May 01 '12 at 10:42