I'm new to Julia and I am trying to implement Julia's multithreading but I believe I am running into the "race condition problem". Here I am plotting the mandelbrot but I believe because of the race condition the array index [n] is messing with the color mapping. I tried using the atomic feature to the index n but apparently i cant use that type as an index. Here are pictures to compare as well as the code block.
Thanks!
module MandelBrot
using Plots
#make some functions for mandelbrot stuff
#find out if a number is part of the set
#remember the mandelbrot is symmetrical about the real number plane
function mandel(c)
#determine if a number is in the set or not in the set -
max_iter = 1000;
bound = 2
z = 0
n = 0
#if the magnitude of z exceeds two we know we are done.
while abs(z)<bound && n<max_iter
z = z^2+c
n+=1
end
return n #if n is 1000 assume c is good, else not of the set
end
#map n to a color
function brot(n)
rgb = 250
m = (n%rgb) /rgb#divide 250
if 0< n <= 250
c = RGB(1,m,0)
elseif 250<n<=500
c = RGB(1-m,1,0)
elseif 500<n<=750
c = RGB(0,1,m)
elseif 750<n<=999
c = RGB(0,1-m,1)
else
c=RGB(0,0,0)
end
return c
#TODO: append this c to an array of color values
end
#mrandom
function mandelbrot(reals,imags)
#generate #real amount of points between -2 and 1
#and #imag amount of points between 0 and i
#determine if any of those combinations are in the mandelbrot set
r = LinRange(-2,1,reals)
i = LinRange(-1,1,imags)
master_list = zeros(Complex{Float64},reals*imags,1)
color_assign = Array{RGB{Float64}}(undef,reals*imags,1)
#n = Threads.Atomic{Int64}(1)
n = 1
Threads.#threads for real_num in r
for imaginary_num in i
#z = complex(real_num, imaginary_num) #create the number
#master_list[n] = z #add it to the list
#color_assign[n,1] = (brot ∘ mandel)(z) #function of function! \circ + tab
#or would this be faster? since we dont change z all the time?
master_list[n] = complex(real_num, imaginary_num)
color_assign[n,1] = (brot ∘ mandel)(complex(real_num, imaginary_num))
n+=1
#Threads.atomic_add!(n,1)
end
end
gr(markerstrokewidth=0,markerstrokealpha=0,markersize=.5,legend=false)
scatter(master_list,markerstrokecolor=color_assign,color=color_assign,aspect_ratio=:equal)
end
#end statement for the module
end
julia> #time m.mandelbrot(1000,1000)
2.260481 seconds (6.01 M allocations: 477.081 MiB, 9.56% gc time)
Here is what should help:
function mandelbrot(reals,imags)
r = LinRange(-2,1,reals)
i = LinRange(0,1,imags)
master_list = zeros(Complex{Float64},reals*imags,1)
color_assign = Array{RGB{Float64}}(undef,reals*imags,1)
Threads.#threads for a in 1:reals
real_num = r[a]
for (b, imaginary_num) in enumerate(i)
n = (a-1)*imags + b
master_list[n] = complex(real_num, imaginary_num)
color_assign[n, 1] = (brot ∘ mandel)(complex(real_num, imaginary_num))
end
end
gr(markerstrokewidth=0,markerstrokealpha=0,markersize=1,legend=false)
scatter(master_list,markerstrokecolor=color_assign,color=color_assign,aspect_ratio=:equal)
end
The approach is to compute n as a function of indices along r and i.
Also note that I use 1:reals and not just enumerate(r) as Threads.#threads does not accept arbitrary iterators.
Note though that your code could probably be cleaned up in other but it is hard to do this without a fully reproducible example.
Related
THERE WAS AN ERROR IN MY CODE. SORRY EVERYBODY. THE REASON WAS THAT THE TIME NEEDED FOR LARGER VALUE OF X IS LARGER.
This is my code:
fit_s = rand(100)
fit_d = rand(300)
LIM = 100
x = [2^i for i in range(-2,2,40)]
y = zeros(length(x))
Threads.#threads for i in 1:length(x)
y[i] = analytic(x[i], fit_s, fit_d, LIM)
end
print(i)
my_function uses the two inputs to produce the output.
The problem is that it does not speed up the execution. With 1 threads it takes 27 s while with 8 threads 21 s(I'm considering only the time of the for loop).
What can I do ?
Thanks in advice.
Function
function alpha(i,n,m)
((n-i)/n)^m - ((n-i-1)/n)^m
end
function beta(i,n,m)
(1-i/n)^(m)
end
function gamma(s, d, fit_s, fit_d, LIM)
n_s = length(fit_s)
n_d = length(fit_d)
app = sort(fit_d, rev=true)[1:LIM]
F_DN = 0.
for i in 1:LIM
j = sum(fit_s .> app[i])
F_DN += alpha(i-1,n_d,d)*beta(j,n_s,s)
end
F_DN
end
function mine_poisson(m,i)
f = Poisson(m)
pdf(f, i)
end
function analytic(m, fit_s, fit_d, LIM)
Z = 1 - exp(-2*m)
F_DN = 0.
intm = trunc(Int, m + 0.5)
if m < 20
intervallo = 1:(intm + 20)
else
app = trunc(Int,m^0.5)*4
intervallo = (intm - app) : (intm+app)
end
for j in intervallo
for k in intervallo
p = mine_poisson(m, k)*mine_poisson(m, j) / Z
F_DN += gamma(j, k, fit_s, fit_d, LIM)*p
end
end
F_DN += exp(-m)*(1-exp(-m))/Z
end
You code looks correct.
There are the following reasons why you might not observe the speedup:
you forgot the -t parameter when starting Julia. Use Threads.nthreads() to check the actual number of threads loaded
your operating system is heavily loaded with other tasks
[most likely] your function my_function is using parallelized code via BLAS. In order to find out the BLAS configuration try:
using LinearAlgebra
LinearAlgebra.BLAS.get_num_threads()
BLAS is used for linear algebra operations such as matrix multiplications. In that case the call my_function would be using most of threads already and hence small speedup is observed
some other libraries such as DataFrames are utilizing threading support for selected operations
other issues such as false sharing or race condition (does not look to be the case in your code)
I have a function that I am attempting to minimize for multiple values. For some values it terminates successfully however for others the error
Warning: Maximum number of function evaluations has been exceeded.
Is the error that is given. I am unsure of the role of maxiter and maxfun and how to increase or decrease these in order to successfully get to the minimum. My understanding is that these values are optional so I am unsure of what the default values are.
# create starting parameters, parameters equal to sin(x)
a = 1
k = 0
h = 0
wave_params = [a, k, h]
def wave_func(func_params):
"""This function calculates the difference between a sinewave (sin(x)) and raw_data (different sin wave)
This is the function that will be minimized by modulating a, b, k, and h parameters in order to minimize
the difference between curves."""
a = func_params[0]
b = 1
k = func_params[1]
h = func_params[2]
y_wave = a * np.sin((x_vals-h)/b) + k
error = np.sum((y_wave - raw_data) * (y_wave - raw_data))
return error
wave_optimized = scipy.optimize.fmin(wave_func, wave_params)
You can try using scipy.optimize.minimize with method='Nelder-Mead' https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html.
https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html#optimize-minimize-neldermead
Then you can just do
minimum = scipy.optimize.minimize(wave_func, wave_params, method='Nelder-Mead')
n_function_evaluations = minimum.nfev
n_iterations = minimum.nit
or you can customize the search algorithm like this:
minimum = scipy.optimize.minimize(
wave_func, wave_params, method='Nelder-Mead',
options={'maxiter': 10000, 'maxfev': 8000}
)
I don't know anything about fmin, but my guess is that it behaves extremely similarly.
import random
l = "lava"
d = "dessert"
f = "forest"
v = "village"
s = "sect"
w = "water"
c = "city"
m = "mountains"
p = "plains"
t = "swamp"
map_list = [l,d,f,v,s,w,c,m,p,t]
map = []
for i in range(50):
map.append([])
def rdm_map(x):
for i in range(50):
map[x].append(random.choice(map_list))
def map_create():
x = 0
while x <= len(map):
rdm_map(x)
x + 1
map_create()
print(map[2][1])
I'm not getting anything for output not even an error code.I'm trying to create a randomly generated game map of descent size but when i went to run it nothing happened i'm thinking since my computer isn't that great its just taking way to long to process but i just wanted to post it on here to double check. If that is the issue is there a way to lessen the load without lessening the map size?
You have the following bugs:
Inside the map_create you must change x + 1 to x += 1. For this reason your script runs for ever.
After that you should change the while x <= len(map): to while x < len(map):. If you keep the previous, you will get a Index Error.
In any case, your code can be further improved. Please try to read some pages of the tutorial first.
Suppose I have some binary mask mask. (e.g. 0b101011011101)
Is there an efficient method of computing all integers k such that k & mask == k? (where & is the bitwise AND operator) (alternatively, k & ~mask == 0)
If mask has m ones, then there are exactly 2m numbers that satisfy this property, so it seems like there should be some kind of process that is O(2m). Enumerating the integers less than the mask is wasteful (though easy to eliminate values that do not apply).
I figured it out... you can identify all the single bit patterns like as follows, since the least significant 1 bit of any integer k is cleared when calculating k & (k-1):
def onebits(x):
while x > 0:
# find least significant 1 bit
xprev = x
x &= x-1
yield x ^ xprev
and then I can use the ruler function to XOR in various combinations of 1 bits to emulate which bits of a counter are toggled each time:
def maskcount(mask):
maskbits = []
m = 0
for ls1 in onebits(mask):
m ^= ls1
maskbits.append(m)
# ruler function modified from
# http://lua-users.org/wiki/LuaCoroutinesVersusPythonGenerators
def ruler(k):
for i in range(k):
yield i
for x in ruler(i): yield x
x = 0
yield x
for k in ruler(len(maskbits)):
x ^= maskbits[k]
yield x
which looks like this:
>>> for x in maskcount(0xc05):
... print format(x, '#016b')
0b00000000000000
0b00000000000001
0b00000000000100
0b00000000000101
0b00010000000000
0b00010000000001
0b00010000000100
0b00010000000101
0b00100000000000
0b00100000000001
0b00100000000100
0b00100000000101
0b00110000000000
0b00110000000001
0b00110000000100
0b00110000000101
An easy way to solve the problem is to find the bits that are set in mask, and then simply count with i, but then replacing the bits of i with corresponding bits from the mask.
def codes(mask):
bits = filter(None, (mask & (1 << i) for i in xrange(mask.bit_length())))
for i in xrange(1 << len(bits)):
yield sum(b for j, b in enumerate(bits) if (i >> j) & 1)
print list(codes(39))
That gives you O(log(N)) work per iteration (where N is the number of bits set in mask).
It's possible to be more efficient, and do O(1) work per iteration by counting using gray codes. With gray code counting, only a single bit changes each iteration so it's possible to efficiently update the current value, v. Obviously this is much harder to understand than the simple solution above.
def codes(mask):
bits = filter(None, (mask & (1 << i) for i in xrange(mask.bit_length())))
blt = dict((1 << i, b) for i, b in enumerate(bits))
p, v = 0, 0
for i in xrange(1 << len(bits)):
n = i ^ (i >> 1)
v ^= blt.get(p^n, 0)
p = n
yield v
print list(codes(39))
A disadvantage of using gray codes is that the results are not returned in numeric order. But luckily that wasn't a condition in the question!
In my attempts to practice Julia, I've made a program which draws a bifurcation diagram. My code is as follows:
function bifur(x0,y0,a=1.3,b=0.4,n=1000,m=10000)
i,x,y=1,x0,y0
while i < n && abs(x) < m
x,y = a - x^2 + y, b * x
i += 1
end
if abs(x) < m
return x
else
return 1000
end
end
la = Float64[];
lx = Float64[];
for a=0:400
for j = 1:1000
x0 = rand()
y0 = rand()
x = bifur(x0,y0,a/100)
if x != 1000
push!(la,a/100)
push!(lx,x)
end
end
end
using Gadfly
myplot = Gadfly.plot( x=la, y=lx , Scale.x_discrete, Scale.y_continuous, Geom.point)
draw(PNG("myplot.png",10inch,8inch),myplot)
The output I get is this image:
In order to make my plot look more like this:
I need to be able to set point sizes to as small as one pixel. Then by increasing the iteration length I should be able to get a better bifurcation diagram. Does anyone know how to set the point sizes in Gadfly diagrams in Julia?
[Just to encapsulate the comments as an answer...]
Gadfly's Theme defaults can be changed. In particular, point_size is probably what you are looking for.
For changing the automatic plot scale/range settings, have a look at Gadfly's Scale params.