From 62cbe3ded47d8e5aef462efda81df6b108cedc10 Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Wed, 10 Nov 2021 14:48:09 -0500 Subject: [PATCH 1/4] llvm, mechanisms/DDM: Pass correct parameter structure for seed resetting The 'params' in this context refers to the parameter structure of the invoked function. Instead we need to pass the mechanism's parameters. Fixes 9b2ab4f16d80a6409760754fe3949586b5dc79ef ("llvm: Add helper function to retrieve and optionally reseed random state") Add comment about seed floating point type. Signed-off-by: Jan Vesely --- psyneulink/core/llvm/builder_context.py | 4 +++- .../components/mechanisms/processing/integrator/ddm.py | 5 +++-- tests/mechanisms/test_ddm_mechanism.py | 2 -- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/psyneulink/core/llvm/builder_context.py b/psyneulink/core/llvm/builder_context.py index 29bc0380e8c..6e397eaada0 100644 --- a/psyneulink/core/llvm/builder_context.py +++ b/psyneulink/core/llvm/builder_context.py @@ -261,7 +261,9 @@ def get_random_state_ptr(self, builder, component, state, params): # Modulated params are usually single element arrays seed_ptr = builder.gep(seed_ptr, [self.int32_ty(0), self.int32_ty(0)]) new_seed = builder.load(seed_ptr) - # FIXME: the seed should ideally be integer already + # FIXME: The seed should ideally be integer already. + # However, it can be modulated and we don't support, + # passing integer values as computed results. new_seed = builder.fptoui(new_seed, used_seed.type) seeds_cmp = builder.icmp_unsigned("!=", used_seed, new_seed) diff --git a/psyneulink/library/components/mechanisms/processing/integrator/ddm.py b/psyneulink/library/components/mechanisms/processing/integrator/ddm.py index 8df938d511e..745d5c9c80d 100644 --- a/psyneulink/library/components/mechanisms/processing/integrator/ddm.py +++ b/psyneulink/library/components/mechanisms/processing/integrator/ddm.py @@ -1127,8 +1127,9 @@ def _gen_llvm_invoke_function(self, ctx, builder, function, params, state, varia threshold = pnlvm.helpers.load_extract_scalar_array_one(builder, threshold_ptr) # Load mechanism state to generate random numbers - state = builder.function.args[1] - random_state = ctx.get_random_state_ptr(builder, self, state, params) + mech_params = builder.function.args[0] + mech_state = builder.function.args[1] + random_state = ctx.get_random_state_ptr(builder, self, mech_state, mech_params) random_f = ctx.get_uniform_dist_function_by_state(random_state) random_val_ptr = builder.alloca(random_f.args[1].type.pointee) builder.call(random_f, [random_state, random_val_ptr]) diff --git a/tests/mechanisms/test_ddm_mechanism.py b/tests/mechanisms/test_ddm_mechanism.py index f94233202b7..ef9f2ac0643 100644 --- a/tests/mechanisms/test_ddm_mechanism.py +++ b/tests/mechanisms/test_ddm_mechanism.py @@ -237,8 +237,6 @@ def test_selected_input_array(self): @pytest.mark.benchmark @pytest.mark.parametrize('prng', ['Default', 'Philox']) def test_DDM_Integrator_Bogacz(benchmark, mech_mode, prng): - if prng == 'Philox': - pytest.skip("Known broken") stim = 10 T = DDM( name='DDM', From 2e2bc63caaad11e890d8b94404da9dd6aa069aaf Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Wed, 10 Nov 2021 16:01:50 -0500 Subject: [PATCH 2/4] llvm/codegen: Use correct helper to get state member offset Indexing into state should use 'get_state_ptr' Signed-off-by: Jan Vesely --- psyneulink/core/llvm/codegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psyneulink/core/llvm/codegen.py b/psyneulink/core/llvm/codegen.py index ceff670e733..1ad7df72155 100644 --- a/psyneulink/core/llvm/codegen.py +++ b/psyneulink/core/llvm/codegen.py @@ -722,7 +722,7 @@ def gen_composition_exec(ctx, composition, *, tags:frozenset): with _gen_composition_exec_context(ctx, composition, tags=tags) as (builder, data, params, cond_gen): state, _, comp_in, _, cond = builder.function.args - nodes_states = helpers.get_param_ptr(builder, composition, state, "nodes") + nodes_states = helpers.get_state_ptr(builder, composition, state, "nodes") # Allocate temporary output storage output_storage = builder.alloca(data.type.pointee, name="output_storage") From 196670111025cd920a1df2b7b7450b204480e3fa Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Wed, 10 Nov 2021 16:02:48 -0500 Subject: [PATCH 3/4] llvm/helpers: Add basic sanity checks to get_{param,state}_ptr helpers Signed-off-by: Jan Vesely --- psyneulink/core/llvm/helpers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/psyneulink/core/llvm/helpers.py b/psyneulink/core/llvm/helpers.py index 84d5d89b8ea..dce10f5ba15 100644 --- a/psyneulink/core/llvm/helpers.py +++ b/psyneulink/core/llvm/helpers.py @@ -81,12 +81,18 @@ def uint_min(builder, val, other): def get_param_ptr(builder, component, params_ptr, param_name): + # check if the passed location matches expected size + assert len(params_ptr.type.pointee) == len(component.llvm_param_ids) + idx = ir.IntType(32)(component.llvm_param_ids.index(param_name)) return builder.gep(params_ptr, [ir.IntType(32)(0), idx], name="ptr_param_{}_{}".format(param_name, component.name)) def get_state_ptr(builder, component, state_ptr, stateful_name, hist_idx=0): + # check if the passed location matches expected size + assert len(state_ptr.type.pointee) == len(component.llvm_state_ids) + idx = ir.IntType(32)(component.llvm_state_ids.index(stateful_name)) ptr = builder.gep(state_ptr, [ir.IntType(32)(0), idx], name="ptr_state_{}_{}".format(stateful_name, From 695dc51cf3912c6f3b3495e89cfab0fb94bb1655 Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Wed, 10 Nov 2021 16:38:30 -0500 Subject: [PATCH 4/4] llvm, autodiffcomposition: Add id for the optimizer state Signed-off-by: Jan Vesely --- psyneulink/library/compositions/autodiffcomposition.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/psyneulink/library/compositions/autodiffcomposition.py b/psyneulink/library/compositions/autodiffcomposition.py index c1c8d79df99..8fe17d232f8 100644 --- a/psyneulink/library/compositions/autodiffcomposition.py +++ b/psyneulink/library/compositions/autodiffcomposition.py @@ -557,6 +557,9 @@ def execute(self, report_num=report_num ) + def _get_state_ids(self): + return super()._get_state_ids() + ["optimizer"] + def _get_state_struct_type(self, ctx): comp_state_type_list = ctx.get_state_struct_type(super()) pytorch_representation = self._build_pytorch_representation()