def parallel(self, width, routing=Routing.ROUND_ROBIN, func=None, name=None):
_name = name<EOL>if _name is None:<EOL><INDENT>_name = self.name + '<STR_LIT>'<EOL><DEDENT>_name = self.topology.graph._requested_name(_name, action='<STR_LIT>', func=func)<EOL>if routing is None or routing == Routing.ROUND_ROBIN or routing == Routing.BROADCAST:<EOL><INDENT>op2 = self.topology.graph.addOperator("<STR_LIT>", name=_name)<EOL>if name is not None:<EOL><INDENT>op2.config['<STR_LIT>'] = _name<EOL><DEDENT>op2.addInputPort(outputPort=self.oport)<EOL>if routing == Routing.BROADCAST:<EOL><INDENT>oport = op2.addOutputPort(width, schema=self.oport.schema, routing="<STR_LIT>", name=_name)<EOL><DEDENT>else:<EOL><INDENT>oport = op2.addOutputPort(width, schema=self.oport.schema, routing="<STR_LIT>", name=_name)<EOL><DEDENT>return Stream(self.topology, oport)<EOL><DEDENT>elif routing == Routing.HASH_PARTITIONED:<EOL><INDENT>if (func is None):<EOL><INDENT>if self.oport.schema == streamsx.topology.schema.CommonSchema.String:<EOL><INDENT>keys = ['<STR_LIT:string>']<EOL>parallel_input = self.oport<EOL><DEDENT>elif self.oport.schema == streamsx.topology.schema.CommonSchema.Python:<EOL><INDENT>func = hash<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError("<STR_LIT>".format(self.oport.schema))<EOL><DEDENT><DEDENT>if func is not None:<EOL><INDENT>keys = ['<STR_LIT>']<EOL>stateful = self._determine_statefulness(func)<EOL>hash_adder = self.topology.graph.addOperator(self.topology.opnamespace+"<STR_LIT>", func, stateful=stateful)<EOL>hash_adder._op_def['<STR_LIT>'] = True<EOL>hash_adder._layout(hidden=True)<EOL>hash_schema = self.oport.schema.extend(streamsx.topology.schema.StreamSchema("<STR_LIT>"))<EOL>hash_adder.addInputPort(outputPort=self.oport)<EOL>streamsx.topology.schema.StreamSchema._fnop_style(self.oport.schema, hash_adder, '<STR_LIT>')<EOL>parallel_input = hash_adder.addOutputPort(schema=hash_schema)<EOL><DEDENT>parallel_op = self.topology.graph.addOperator("<STR_LIT>", name=_name)<EOL>if name is not None:<EOL><INDENT>parallel_op.config['<STR_LIT>'] = _name<EOL><DEDENT>parallel_op.addInputPort(outputPort=parallel_input)<EOL>parallel_op_port = parallel_op.addOutputPort(oWidth=width, schema=parallel_input.schema, partitioned_keys=keys, routing="<STR_LIT>")<EOL>if func is not None:<EOL><INDENT>hrop = self.topology.graph.addPassThruOperator()<EOL>hrop._layout(hidden=True)<EOL>hrop.addInputPort(outputPort=parallel_op_port)<EOL>parallel_op_port = hrop.addOutputPort(schema=self.oport.schema)<EOL><DEDENT>return Stream(self.topology, parallel_op_port)<EOL><DEDENT>else :<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>
Split stream into channels and start a parallel region.

Returns a new stream that will contain the contents of
this stream with tuples distributed across its channels.

The returned stream starts a parallel region where all
downstream transforms are replicated across `width` channels.
A parallel region is terminated by :py:meth:`end_parallel`
or :py:meth:`for_each`.

Any transform (such as :py:meth:`map`, :py:meth:`filter`, etc.) in
a parallel region has a copy of its callable executing
independently in parallel. Channels remain independent
of other channels until the region is terminated.

For example with this topology fragment a parallel region
of width 3 is created::

    s = ...
    p = s.parallel(3)
    p = p.filter(F()).map(M())
    e = p.end_parallel()
    e.for_each(E())

Tuples from ``p`` (parallelized ``s``)  are distributed
across three channels, 0, 1 & 2
and are independently processed by three instances of ``F`` and ``M``.
The tuples that pass the filter ``F`` in channel 0 are then mapped
by the instance of ``M`` in channel 0, and so on for channels 1 and 2.

The channels are combined by ``end_parallel`` and so a single instance
of ``E`` processes all the tuples from channels 0, 1 & 2.

This stream instance (the original) is outside of the parallel region
and so any downstream transforms are executed normally.
Adding this `map` transform would result in tuples
on ``s`` being processed by a single instance of ``N``::

    n = s.map(N())

The number of channels is set by `width` which may be an `int` greater
than zero or a submission parameter created by
:py:meth:`Topology.create_submission_parameter`.

With IBM Streams 4.3 or later the number of channels can be
dynamically changed at runtime.

Tuples are routed to channels based upon `routing`, see :py:class:`Routing`.

A parallel region can have multiple termination points, for
example when a stream within the stream has multiple transforms
against it::

    s = ...
    p = s.parallel(3)
    m1p = p.map(M1())
    m2p = p.map(M2())
    p.for_each(E())

    m1 = m1p.end_parallel()
    m2 = m2p.end_parallel()

Parallel regions can be nested, for example::

    s = ...
    m = s.parallel(2).map(MO()).parallel(3).map(MI()).end_parallel().end_parallel()

In this case there will be two instances of ``MO`` (the outer region) and six (2x3) instances of ``MI`` (the inner region).

Streams created by :py:meth:`~Topology.source` or
:py:meth:`~Topology.subscribe` are placed in a parallel region
by :py:meth:`set_parallel`.

Args:
    width (int): Degree of parallelism.
    routing(Routing): Denotes what type of tuple routing to use.
    func: Optional function called when :py:const:`Routing.HASH_PARTITIONED` routing is specified.
        The function provides an integer value to be used as the hash that determines
        the tuple channel routing.
    name (str): The name to display for the parallel region.

Returns:
    Stream: A stream for which subsequent transformations will be executed in parallel.

.. seealso:: :py:meth:`set_parallel`, :py:meth:`end_parallel`