def test_getMultiplicityMap(self): """Test generating a multiplicity map from a coreIdMap.""" inputShape = (10, 10, 2) inputLayer = NxInputLayer(inputShape) layer = NxConv2D(2, 3) layer(inputLayer.input) coreShape = np.array([4, 3, 2]) layerShape = layer.output_shape[1:] numCoresPerAxis = np.ceil(layerShape / coreShape).astype(int) coreIdMap = getCoreIdMapFromCoreShape(coreShape, layerShape, numCoresPerAxis) multiplicityMap = layer.getMultiplicityMap(coreIdMap) if self.verbose: plotMat(multiplicityMap, title='MultiplicityMap') target = [[1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [2, 2, 2, 4, 4, 2, 4, 4, 2, 2], [2, 2, 2, 4, 4, 2, 4, 4, 2, 2], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1], [1, 1, 1, 2, 2, 1, 2, 2, 1, 1]] self.assertTrue(np.array_equal(multiplicityMap, target))
def tryCreatePartition(numCoresPerAxis, coreShape, postLayerPartition, layer, logdir): """Try creating a partition of the layer. Fails if proposed partition exceeds one of the Loihi limits. :param np.ndarray | list | tuple numCoresPerAxis: Number of cores along each layer dimension. :param np.ndarray | list | tuple coreShape: The shape of the largest core. :param Layer postLayerPartition: The subsequent partitioned layer. :param KerasLayer | NxConv2D layer: The layer to partition. :param str logdir: Where to save plots. :return: Valid partition candidate. :rtype: Layer """ outputShape = layer.output_shape[1:] # When using signed spikes the number of channels in the output # is doubled. if hasattr(layer, 'signed'): if layer.signed: outputShape = outputShape[:-1] + (2 * outputShape[-1],) coreIdMap = getCoreIdMapFromCoreShape(coreShape, outputShape, numCoresPerAxis) coreOccupancy = getCoreOccupancy(coreIdMap, numCoresPerAxis) if np.any(coreOccupancy > layer.maxNumCompartments): return multiplicityMap = layer.getMultiplicityMap(coreIdMap) partitionCandidate = Layer(layer.name, layer.__class__.__name__, layer.compartmentKwargs, layer.connectionKwargs, coreIdMap, multiplicityMap, postLayerPartition) # Pass coreOccupancy to partitionCandidate here only to be able to plot it # later when the partition has been stored to disk. partitionCandidate.coreOccupancy = coreOccupancy partitionCandidate = layer.compile(partitionCandidate) if partitionCandidate is None: print('.', end='', flush=True) return layer.validatePartition(partitionCandidate) layer.visualizePartition(logdir, partitionCandidate, coreIdMap, coreOccupancy, multiplicityMap=multiplicityMap) print('x', end='', flush=True) return partitionCandidate
def test_getCoreIdMapFromCoreShape2(self): """Test generating the coreIdMap given a coreShape.""" inputShape = (4, 4, 2) inputLayer = NxInputLayer(inputShape) layer = NxConv2D(2, 3) layer(inputLayer.input) coreShape = np.array([2, 1, 2]) layerShape = layer.output_shape[1:] numCoresPerAxis = np.ceil(layerShape / coreShape).astype(int) coreIds = getCoreIdMapFromCoreShape(coreShape, layerShape, numCoresPerAxis) target = np.array([[[0, 0], [1, 1]], [[0, 0], [1, 1]]]) self.assertTrue(np.array_equal(coreIds, target)) if self.verbose: plotMat(coreIds[:, :, 0], title='coreIds[:, :, 0]') plotMat(coreIds[:, :, 1], title='coreIds[:, :, 1]')
def test_compressConnections(self): """Check axon compression.""" inputShapes = np.array([[7, 7, 2], [32, 32, 3], [32, 32, 3], [27, 26, 2], [32, 30, 2], [30, 35, 2], [7, 7, 2], [20, 25, 2], [7, 7, 2], [30, 35, 2], [7, 7, 2], [30, 35, 2]]) layerArgs = np.array([[2, 3], [2, 3], [2, 3], [2, 1], [2, 2], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3]]) layerKwargs = np.array([ { 'synapseEncoding': 'sparse' }, { 'synapseEncoding': 'sparse' }, { 'synapseEncoding': 'sparse', 'strides': 2 }, { 'synapseEncoding': 'sparse', 'strides': 2 }, { 'synapseEncoding': 'sparse', 'strides': 2 }, { 'synapseEncoding': 'sparse', 'strides': 2, 'padding': 'same' }, { 'synapseEncoding': 'runlength' }, { 'synapseEncoding': 'runlength', 'strides': 2, 'padding': 'same' }, { 'synapseEncoding': 'dense1' }, { 'synapseEncoding': 'dense1', 'strides': 2, 'padding': 'same' }, { 'synapseEncoding': 'dense2' }, { 'synapseEncoding': 'dense2', 'strides': 2, 'padding': 'same' }, ]) coreShapes = np.array([[5, 5, 2], [30, 10, 2], [10, 5, 2], [7, 13, 2], [16, 5, 2], [8, 9, 2], [5, 5, 2], [6, 9, 2], [5, 5, 2], [15, 10, 2], [5, 5, 2], [6, 9, 2]]) # numOutputAxons (second column) is expected to be zero because we are # looking at the output layer. expectedResults = np.array([[14, 0, 900, 281, 378], [108, 0, 29160, 6873, 10080], [198, 0, 4050, 2430, 2592], [52, 0, 56, 42, 28], [60, 0, 768, 528, 384], [144, 0, 1408, 808, 868], [14, 0, 900, 288, 371], [104, 0, 928, 524, 580], [14, 0, 900, 660, 427], [72, 0, 1408, 1226, 840], [14, 0, 3587, 290, 700], [216, 0, 2920, 874, 1052]]) doTest = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], bool) np.random.seed(0) for inputShape, args, kwargs, coreShape, expectedResult in \ zip(inputShapes[doTest], layerArgs[doTest], layerKwargs[doTest], coreShapes[doTest], expectedResults[doTest]): with self.subTest(inputShape=inputShape, args=args, kwargs=kwargs, coreShape=coreShape, expectedResult=expectedResult): # The Keras layer initializer does not know how to handle # np.int types. Convert to builtin int manually. args = list(args) args[1] = int(args[1]) inputLayer = NxInputLayer(tuple(inputShape)) layer = NxConv2D(*args, **kwargs) layer(inputLayer.input) # Assumes that this layer will never go beyond one chip. layer.coreCounter = 0 layerShape = layer.output_shape[1:] numCoresPerAxis = np.ceil(layerShape / coreShape).astype(int) coreIdMap = getCoreIdMapFromCoreShape(coreShape, layerShape, numCoresPerAxis) multiplicityMapPre = np.ones(layer.input_shape[1:-1], int) postLayerPartition = getDummyLayer(layer.output_shape[1:]) partitionCandidate = Layer(layer.name, '', layer.compartmentKwargs, layer.connectionKwargs, coreIdMap, multiplicityMapPre, postLayerPartition) partitionCandidate = layer.compile(partitionCandidate) try: layer.validatePartition(partitionCandidate) finally: layer.deleteKernelIdMap() layer.deleteKernelIdMap() result = [ partitionCandidate.numInputAxons, partitionCandidate.numOutputAxons, partitionCandidate.numSyn, partitionCandidate.numSynEntries, partitionCandidate.numSynMemWords ] self.verbose = True if self.verbose: print(result) for er, r in zip(expectedResult, result): self.assertEqual(er, r)