Skip to content

Instantly share code, notes, and snippets.

@mikewl
Last active August 9, 2017 15:16
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save mikewl/cac69ae7f9fcc3b3158bcb462c1512a9 to your computer and use it in GitHub Desktop.
#setup GPUArrays and CUDA backend
#using CUDAnative
using GPUArrays
JLBackend.init()
using StaticArrays
#overload for simple julia side work
import Base: <,>,==
#constants used in evolution
const absMax = 5.0f0
const D = 30
const PS = 2000
const gen = 1000
const T_SIZE = 20
const MR = 0.3f0
const MA = 0.2f0
const XR = 0.5f0
struct RandomResult{T}
state::NTuple{4, Cuint}
value::T
end
function TausStep(z::Unsigned, S1::Integer, S2::Integer, S3::Integer, M::Unsigned)
b = (((z << S1) z) >> S2)
return (((z & M) << S3) b)
end
LCGStep(z::Unsigned, A::Unsigned, C::Unsigned) = A * z + C
function Random(state::NTuple{4, T}) where T <: Unsigned
state = (
TausStep(state[1], Cint(13), Cint(19), Cint(12), T(4294967294)),
TausStep(state[2], Cint(2), Cint(25), Cint(4), T(4294967288)),
TausStep(state[3], Cint(3), Cint(11), Cint(17), T(4294967280)),
LCGStep(state[4], T(1664525), T(1013904223))
)
return RandomResult(
state,
Float32(2.3283064f-10 * (state[1] state[2] state[3] state[4]))
)
end
function gpu_rand(states, tstate)
threadid = tstate
stateful_rand = Random(states[threadid])
states[threadid] = stateful_rand.state
return stateful_rand.value
end
#immutable individual
struct Individual
chromosome::SVector{D, Float32}
fitness::Float32
function Individual(size::Int, fitness)
chromosome = SVector{D}(rand(Float32, D) * absMax * 2f0 - absMax)
return new(chromosome, fitness(new(chromosome,0.0f0)))
end
Individual(data, fitness::Float32) = new(data, fitness)
end
<(x::Individual, y::Individual) = x.fitness < y.fitness
>(x::Individual, y::Individual) = x.fitness > y.fitness
==(x::Individual, y::Individual) = x.fitness == y.fitness
#fitness function
function sphereFitness(input::Individual)
total::Float32 = 0.0f0
for gene in input.chromosome
total += gene*gene
end
return total
end
function crossover(parent1::Individual, parent2::Individual, states, tstate)
xover_chance = XR
if gpu_rand(states, tstate) < xover_chance
newChromosome = zeros(Float32, D)
for i = 1:length(newChromosome)
@inbounds newChromosome[i] = (gpu_rand(states, tstate) < 0.5f0)? parent1.chromosome[i]:parent2.chromosome[i]
end
return Individual(SVector{D}(newChromosome), 0.0f0)
else
return parent1
end
end
#tournament selection
function select(pop, states, tstate)
pos = round(Int32, gpu_rand(states, tstate)*(PS-1))+1
bestitem = pop[pos]
for i = 2:T_SIZE
pos = round(Int32, gpu_rand(states, tstate)*(PS-1))+1
item = pop[pos]
if bestitem > item
bestitem = item
end
end
return bestitem
end
function mutate(input::Individual, states, tstate)
mut_amp = MA
mut_rate = MR
newChromosome = zeros(Float32, D)
for i = 1:length(input.chromosome)
newChromosome[i] += gpu_rand(states, tstate) < mut_rate ?
input.chromosome[i] + gpu_rand(states, tstate)*mut_amp*2 - mut_amp : input.chromosome[i]
end
return Individual(SVector{D}(newChromosome), 0.0f0)
end
function genIndividuals(state, pop, newpop, states)
tstate = linear_index(newpop, state)
newInd = crossover(select(pop, states, tstate),
select(pop, states, tstate), states, tstate)
newInd = mutate(newInd, states, tstate)
newInd = Individual(newInd.chromosome, sphereFitness(newInd))
newpop[tstate] = newInd
return
end
function best(pop)
best = pop[1]
for item in pop
if best > item
best = item
end
end
return best
end
function main()
pop = GPUArray(Individual[Individual(D, sphereFitness) for i = 1:PS])
oldpop = GPUArray(Individual[Individual(D, sphereFitness) for i = 1:PS])
states = GPUArray(NTuple{4, UInt32}[(rand(UInt32), rand(UInt32), rand(UInt32), rand(UInt32)) for i = 1:PS])
printpop = [oldpop;]
println(best(oldpop).fitness)
for i = 1:gen
gpu_call(genIndividuals, oldpop, (oldpop, pop, states))
temp = pop
pop = oldpop
oldpop = pop
#println(best(oldpop).fitness)
end
oldpop = [oldpop;]
println(best(oldpop).fitness)
return oldpop
end
@time main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment