So I decided to dig deeper. Basically the standard crand() is not that good. So instead I searched for the fastest Mersenne Twister there is. I downloaded the latest code and compiled it in the fastest way for my architecture.
And after all that trouble we got the performance down to 18 seconds. Still slower that Julia‘s 16 seconds.
$ time ./eulerfast
Euler : 2.71824
real 0m18.075s
user 0m18.085s
sys 0m0.001s
Probably, we could do a bit better with more tweaks, and probably exceed Julia‘s performance with some effort. But at that point, I got tired of pushing this further. The thing I love about Julia is how well it is engineered and hassle free. It is quite phenomenal the performance you get out of it, with so little effort. And for basic technical computing things, like random number generation, you don’t have to dig hard for a better library. The “batteries included” choices in the Julia‘s standard library are pretty good.
it is quite nice though that you can rely on the quality of Base for numerics.
On e-day, I came across this cool tweet from Fermat’s library
Happy e-day of the century! 2 7 18
Curious fact about Euler's Number: Pick a uniformly random number in [0,1] and repeat until the sum of the numbers picked is >1. You'll on average pick e≈2.718… numbers! pic.twitter.com/P0wx9hQu79
$ time ./a.out
Euler : 2.71829
real 0m36.213s
user 0m36.238s
sys 0m0.004s
For the curios, I am using this version of Julia
julia> versioninfo()
Julia Version 0.6.3-pre.0
Commit 93168a6 (2017-12-18 07:11 UTC)
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.9.1 (ORCJIT, haswell)
Now one should not put too much emphasis on such micro benchmarks. However, I found this a very curious examples when a high level language like Julia could be twice as fast a c. The Julia language authors must be doing some amazing mojo.
Mathematical recreation is fun. I came across a nice Mind your Decisions video and thought it would be cool to use Julia to find that special number. Have a look at the video here before we continue
Julia can be amazingly expressive. In line 14 are getting all the prime factors of all the numbers from 1 to 100 using the map function. We are using the type BigInt since will be generating pretty large numbers. The standard Int will simply overflow. We then use reduce to get all the common factors for the numbers from 1 to 100.
If your are slight confused lets take a bit slower. First we generate a one dimensional array of BigInts from 1 to 100.
BigInt.(1:100)
This makes use of Julia‘s very powerful dot factorization syntax. We then map that array into another array of Primes.Factorization{BigInt} through the factor function in the Primes package. The Primes.Factorization type is subtype of Associative. I learned that from reading the implementation.
The cool thing about Associative types that the can be very conveniently accessed. Lets have a closer look.
a=factor(24)println(a)
yields
Primes.Factorization(2=>3,3=>1)
That is \(2^3 3\)
You can then do the following
print(a[2])
yielding
3
This means that the number 24 has a 2 raised to the third power as a factor.
Or, be more adventurous and try
print(a[5])
which will print a
0
This makes perfect sense as \(5^0=1\) and 1 is always a factor of any number. We will always get 0 exponent for any number that is not a prime factor of a given number. The Primes.jl package authors have done great use of Julia‘s very powerful type system.
To solve this problem we need to look at all the prime factors for all the numbers from 1 to 100 find the highest exponent of the of each of those prime factors. To do that we implement the getBigestFactor function when does that for any two prime factorizations. We plug that into reduce and et voilà!
Finally we multiply them to get our special number at line 16
n=69720375229712477164533808935312303556800
Are we done yet?
As the saying goes “there is more than one way to skin a cat”. Some are more elegant than others.
Here is a more elegant and computationally more efficient way.
Here we just get the prime numbers in the range from 1 to n (line 3). Using those primes we then get the highest exponents that will not yield a number outside the range (line 4). Finally, we package everything as a Primes.Factorization (line 5).
I had a recent Ubuntu install with customizations that I wanted to be able to put it on a USB, boot into it on another machine and be able to modify its contents by, installing new packages, editing files, etc…
PinguyBuilder to the rescue
So after a number of false starts. I stumbled upon PinguyBuilder. I followed the excellent instructions at maketecheasier, with the slight modification of checking the PinguyBuilder site for the the latest version. I used the backup option to get all the tweaks on home directory, and my none deb packages in. My Ubuntu was a derivative the standard Xubuntu 16.04 distro.
Moving the ISO to the USB
The generated iso file could then be installed usb-creator-gtk, or if are working on windows, Rufus. At this point I could nicely boot using my USB stick. I could not, however, write anything persistently on the USB. If I create some file, and then reboot, it would be gone!
Making the USB persistent
First I need to create casper-rw file that would be identified by boot-loader as space to write on. I was happy with 2GB, so this what I did by adopting the instructions on StackExchange post:
I created an empty 2GB file
ddif=/dev/zero of=casper-rw bs=1M count=2048
You can changed count to whatever size of persistent storage you want. I then had to format that space into something that Linux would be able to read
mkfs.ext4 -F casper-rw
The next step was to change /boot/grub/grub.cfg file on the USB to have the following menu-entry at the beginning.
menuentry "Xubuntu in persistent mode"{setgfxpayload=keep
linux /casper/vmlinuz file=/cdrom/preseed/custom.seed boot=casper persistent iso-scan/filename=${iso_path} quiet splash --
initrd /casper/initrd.gz
}
Finally, I modified /isolinux/isolinux.cfg to include the extra label
label persistent
menu label live - boot the Live System
kernel /casper/vmlinuz
append file=/cdrom/preseed/custom.seed boot=casper persistent initrd=/casper/initrd.gz quiet splash --
I worry less about the damage to live and property from acts of terror, than the waves of hate that soon follow. The damage due to hate is always much worse. Hate brings out the worst in humans. It locks the mind in inescapable focus on violence. All noble ideas, and worthy aspirations fall by the wayside as survival becomes the primary preoccupation. When that happens, I sense that the terrorists have already won.
أرى نفسي أقل قلقاً من الموت و الدمار الناتج من الأعمال الإرهابية بالمقارنة لموجات الكراهية التي تتبعها. الضرر و الخسارة الناتجة من الكراهية التي تولدها هذه الأعمال أشد خطورة.
الكراهية تسقم القلوب و تبرز أقبح ما في البشر.
الكراهية تسجن العقل في دائرة لا نهائية في التركيز علي العنف.
كل الأفكار النبيلة و الطموحات الشريفة تسقط عندما يكون الهم الشاغل هو البقاء.
عندما يحدث ذالك أشعر أن الإرهاب قد نال غايته.
A decision was wise, even though it led to disastrous consequences, if the evidence at hand indicated it was the best one to make; and a decision was foolish, even though it led to the happiest possible consequences, if it was unreasonable to expect those consequences.
Recently I ran into a nasty situation on Kubuntu desktop where a host of crucial KDE components would cease to work. Chiefly amongst them were:
No instances of Dolphin would start
The kickoff launcher would not work
The KDE activity manager was crashing.
I suspected the Nepomuk might be the culprit and I was right. I stopped it by running
qdbus org.kde.NepomukServer /nepomukserver quit
I then wiped out its data by running
rm -r .kde/share/apps/nepomuk/
Finally I got it started again by runing
nepomukserver
…and my problems were solved.
Trying to search for a solution to this problem, I found people suggesting that one would wipe the ~/.kde folder and start afresh. That sounded too drastic and a great deal of my customizations would have been lost in the process.
The gods they make capture their fears, their ignorance, and their desire to control.
Their gods share their grotesque outlook, yet they fully capture their aspirations.
Aspirations of dominance, control, and subjugation of others.
Aspirations of meek and mean-spirited human “beings”.
The wretches are blind to human potential!
Recently I wanted to download all the movies in Mackay’s information theory course. That was a great deal of files and I though it would too tedious to try to do it using the browser or even manual wget. So digging around, I found this decent tutorial on python HTML processing. I also dug around some information on parsing URLs. I combined that with my knowledge of python’s subprocess and put together this nice piece of code.
#!/usr/bin/python
importsgmllib
classMyParser(sgmllib.SGMLParser): "A simple parser class."
defparse(self,s): "Parse the given string 's'." self.feed(s) self.close()
def__init__(self,verbose=0): "Initialise an object, passing 'verbose' to the superclass."