Skip to content

Commit

Permalink
plus phase on GPU
Browse files Browse the repository at this point in the history
  • Loading branch information
rcoreilly committed Nov 26, 2024
1 parent f98952d commit e64e931
Show file tree
Hide file tree
Showing 35 changed files with 337 additions and 248 deletions.
109 changes: 53 additions & 56 deletions axon/act-layer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

109 changes: 53 additions & 56 deletions axon/act-layer.goal
Original file line number Diff line number Diff line change
Expand Up @@ -1043,9 +1043,60 @@ func (ly *LayerParams) PlusPhaseNeuron(ctx *Context, ni, di uint32) {
Neurons[ni, di, Gsahp] = ly.Acts.Sahp.GsAHP(sahpN)
}

//gosl:end
// PlusPhasePost does special algorithm processing at end of plus
func (ly *LayerParams) PlusPhasePost(ctx *Context) {
ly.PlusPhaseActAvg(ctx)
ly.PhaseDiffFromActs(ctx) // GPU syncs down the state before this
np := ly.Indexes.NPools
if ly.Type == PTMaintLayer && ly.CT.OFCposPT.IsTrue() {
for spi := uint32(1); spi < np; spi++ {
for di := uint32(0); di < ctx.NData; di++ {
pi := ly.PoolIndex(spi)
val := PoolAvgMax(AMCaSpkD, AMCycle, Avg, pi, di)
GlobalVectors[GvOFCposPTMaint, uint32(pi-1), di] = val
}
}
}

if ly.Acts.Decay.OnRew.IsTrue() {
for di := uint32(0); di < ctx.NData; di++ {
hasRew := (GlobalScalars[GvHasRew, di] > 0)
giveUp := (GlobalScalars[GvGiveUp, di] > 0)
if hasRew || giveUp {
ly.DecayState(ctx, di, 1, 1, 1) // note: GPU will get, and GBuf are auto-cleared in NewState
for spi := uint32(0); spi < np; spi++ { // also clear the pool stats: GoalMaint depends on these..
pi := ly.PoolIndex(spi)
PoolAvgMaxZero(pi, di)
}
}
}
}
if ly.Type == MatrixLayer {
ly.MatrixGated(ctx)
}
}

// PlusPhaseActAvg updates ActAvg and DTrgAvg at the plus phase
// Note: could be done on GPU but not worth it at this point..
func (ly *LayerParams) PlusPhaseActAvg(ctx *Context) {
nn := ly.Indexes.NNeurons
for lni := uint32(0); lni < nn; lni++ {
ni := ly.Indexes.NeurSt + lni
if NeuronIsOff(ni) {
continue
}
dTrgSum := float32(0)
avgSum := float32(0)
for di := uint32(0); di < ctx.NData; di++ {
dTrgSum += ly.LearnTrgAvgErrLRate() * (Neurons[ni, di, CaSpkP] - Neurons[ni, di, CaSpkD])
avgSum += ly.Acts.Dt.LongAvgDt * (Neurons[ni, di, ActM] - NeuronAvgs[ni, ActAvg])
}
NeuronAvgs[ni, DTrgAvg] += dTrgSum
NeuronAvgs[ni, ActAvg] += avgSum
}
}

// todo: determine how much of this can go directly into layerparams / gosl
//gosl:end

// InitExt initializes external input state.
// Should be called prior to ApplyExt on all layers receiving Ext input.
Expand Down Expand Up @@ -1226,60 +1277,6 @@ func (ly *Layer) UpdateExtFlags(ctx *Context) {
}
}

// PlusPhasePost does special algorithm processing at end of plus
func (ly *Layer) PlusPhasePost(ctx *Context) {
ly.PlusPhaseActAvg(ctx)
ly.PhaseDiffFromActs(ctx) // GPU syncs down the state before this
np := ly.NPools
if ly.Type == PTMaintLayer && ly.Name == "OFCposPT" {
for spi := uint32(1); spi < np; spi++ {
for di := uint32(0); di < ctx.NData; di++ {
pi := ly.Params.PoolIndex(spi)
val := PoolAvgMax(AMCaSpkD, AMCycle, Avg, pi, di)
GlobalVectors[GvOFCposPTMaint, uint32(pi-1), di] = val
}
}
}

if ly.Params.Acts.Decay.OnRew.IsTrue() {
for di := uint32(0); di < ctx.NData; di++ {
hasRew := (GlobalScalars[GvHasRew, di] > 0)
giveUp := (GlobalScalars[GvGiveUp, di] > 0)
if hasRew || giveUp {
ly.DecayState(ctx, di, 1, 1, 1) // note: GPU will get, and GBuf are auto-cleared in NewState
for spi := uint32(0); spi < np; spi++ { // also clear the pool stats: GoalMaint depends on these..
pi := ly.Params.PoolIndex(spi)
PoolAvgMaxZero(pi, di)
}
}
}
}
switch ly.Type {
case MatrixLayer:
ly.Params.MatrixGated(ctx)
}
}

// PlusPhaseActAvg updates ActAvg and DTrgAvg at the plus phase
// Note: could be done on GPU but not worth it at this point..
func (ly *Layer) PlusPhaseActAvg(ctx *Context) {
nn := ly.NNeurons
for lni := uint32(0); lni < nn; lni++ {
ni := ly.NeurStIndex + lni
if NeuronIsOff(ni) {
continue
}
dTrgSum := float32(0)
avgSum := float32(0)
for di := uint32(0); di < ctx.NData; di++ {
dTrgSum += ly.Params.LearnTrgAvgErrLRate() * (Neurons[ni, di, CaSpkP] - Neurons[ni, di, CaSpkD])
avgSum += ly.Params.Acts.Dt.LongAvgDt * (Neurons[ni, di, ActM] - NeuronAvgs[ni, ActAvg])
}
NeuronAvgs[ni, DTrgAvg] += dTrgSum
NeuronAvgs[ni, ActAvg] += avgSum
}
}

// TargToExt sets external input Ext from target values Target
// This is done at end of MinusPhase to allow targets to drive activity in plus phase.
// This can be called separately to simulate alpha cycles within theta cycles, for example.
Expand Down
22 changes: 7 additions & 15 deletions axon/act-net.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 7 additions & 15 deletions axon/act-net.goal
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,8 @@ func (nt *Network) PlusPhase() {
pd := int(nix.NPools * ctx.NData)
RunPlusPhasePool(pd)
RunPlusPhaseNeuron(nd)
RunPlusPhasePost(int(nix.NLayers))
RunDoneLayersNeurons()
nt.PlusPhasePost()
ToGPULayersNeurons()
// todo:
// nt.GPU.SyncStateToGPU()
}

// PlusPhasePost happens on the CPU always.
func (nt *Network) PlusPhasePost() {
ctx := nt.Context()
for _, ly := range nt.Layers {
if ly.Off {
continue
}
ly.PlusPhasePost(ctx)
}
}

// TargToExt sets external input Ext from target values Target
Expand Down Expand Up @@ -368,6 +354,12 @@ func PlusPhaseNeuron(i uint32) { //gosl:kernel
Layers[li].PlusPhaseNeuron(ctx, ni, di)
}

// PlusPhasePost does special algorithm post processing.
func PlusPhasePost(li uint32) { //gosl:kernel
ctx := GetCtx(0)
Layers[li].PlusPhasePost(ctx)
}

// GPUTestWrite is the kernel over Neurons * Data for testing
// the unique writing of data on GPU.
func GPUTestWrite(i uint32) { //gosl:kernel
Expand Down
17 changes: 13 additions & 4 deletions axon/deep-layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package axon

import (
"cogentcore.org/core/goal/gosl/slbool"
"cogentcore.org/core/math32"
)

Expand All @@ -14,10 +15,16 @@ import (
// CaSpkP integrated spiking values in Super layers -- thresholded.
type BurstParams struct {

// Relative component of threshold on superficial activation value, below which it does not drive Burst (and above which, Burst = CaSpkP). This is the distance between the average and maximum activation values within layer (e.g., 0 = average, 1 = max). Overall effective threshold is MAX of relative and absolute thresholds.
// Relative component of threshold on superficial activation value,
// below which it does not drive Burst (and above which, Burst = CaSpkP).
// This is the distance between the average and maximum activation values
// within layer (e.g., 0 = average, 1 = max). Overall effective threshold
// is MAX of relative and absolute thresholds.
ThrRel float32 `max:"1" default:"0.1"`

// Absolute component of threshold on superficial activation value, below which it does not drive Burst (and above which, Burst = CaSpkP). Overall effective threshold is MAX of relative and absolute thresholds.
// Absolute component of threshold on superficial activation value,
// below which it does not drive Burst (and above which, Burst = CaSpkP).
// Overall effective threshold is MAX of relative and absolute thresholds.
ThrAbs float32 `min:"0" max:"1" default:"0.1"`

pad, pad1 float32
Expand Down Expand Up @@ -47,10 +54,12 @@ type CTParams struct {
// decay time constant for context Ge input -- if > 0, decays over time so intrinsic circuit dynamics have to take over. For single-step copy-based cases, set to 0, while longer-time-scale dynamics should use 50 (80 for 280 cycles)
DecayTau float32 `default:"0,50,70"`

// OFCposPT is set for the OFCposPT PTMaintLayer, which sets the
// GvOFCposPTMaint global variable.
OFCposPT slbool.Bool

// 1 / tau
DecayDt float32 `display:"-" json:"-" xml:"-"`

pad float32
}

func (cp *CTParams) Update() {
Expand Down
Loading

0 comments on commit e64e931

Please sign in to comment.