I'm for (1) and am not sure about the feasibility of (2) without having an
escape hatch that allows a pipeline author to specify a coder to handle
their special case.

On Tue, Aug 1, 2017 at 2:15 PM, Reuven Lax <re...@google.com.invalid> wrote:

> One interesting wrinkle: I'm about to propose a set of semantics for
> snapshotting/in-place updating pipelines. Part of this proposal is the
> ability to write pipelines to "upgrade" snapshots to make them compatible
> with new graphs. This relies on the ability to have two separate coders for
> the same type - the old coder and the new coder - in order to handle the
> case where the user has changed coders in the new pipeline.
>
> On Tue, Aug 1, 2017 at 2:12 PM, Robert Bradshaw
> <rober...@google.com.invalid
> > wrote:
>
> > There are two concerns in this thread:
> >
> > (1) Getting rid of PCollection.setCoder(). Everyone seems in favor of
> this
> > (right?)
> >
> > (2) Deprecating specifying Coders in favor of specifying TypeDescriptors.
> > I'm generally in favor, but it's unclear how far we can push this
> through.
> >
> > Let's at least do (1), and separately state a preference for (2), seeing
> > how fare we can push it.
> >
> > On Thu, Jul 27, 2017 at 9:13 PM, Kenneth Knowles <k...@google.com.invalid
> >
> > wrote:
> >
> > > Another thought on this: setting a custom coder to support a special
> data
> > > distribution is likely often a property of the input to the pipeline.
> So
> > > setting a coder during pipeline construction - more generally, when
> > writing
> > > a composite transform for reuse - you might not actually have the
> needed
> > > information. But setting up a special indicator type descriptor lets
> your
> > > users map that type descriptor to a coder that works well for their
> data.
> > >
> > > But Robert's example of RawUnionValue seems like a deal breaker for all
> > > approaches. It really requires .getCoder() during expand() and
> explicitly
> > > building coders encoding information that is cumbersome to get into a
> > > TypeDescriptor. While making up new type languages is a comfortable
> > > activity for me :-) I don't think we should head down that path, for
> our
> > > users' sake. So I'll stop hoping we can eliminate this pain point for
> > now.
> > >
> > > Kenn
> > >
> > > On Thu, Jul 27, 2017 at 8:48 PM, Kenneth Knowles <k...@google.com>
> wrote:
> > >
> > > > On Thu, Jul 27, 2017 at 11:18 AM, Thomas Groh
> <tg...@google.com.invalid
> > >
> > > > wrote:
> > > >
> > > >> introduce a
> > > >> new, specialized type to represent the restricted
> > > >> (alternatively-distributed?) data. The TypeDescriptor for this type
> > can
> > > >> map
> > > >> to the specialized coder, without having to perform a significant
> > degree
> > > >> of
> > > >> potentially wasted encoding work, plus it includes the assumptions
> > that
> > > >> are
> > > >> being made about the distribution of data.
> > > >>
> > > >
> > > > This is a very cool idea, in theory :-)
> > > >
> > > > For complex types with a few allocations involved and/or nontrivial
> > > > deserialization, or when a pipeline does a lot of real work, I think
> > the
> > > > wrapper cost won't be perceptible.
> > > >
> > > > But  for more primitive types in pipelines that don't really do much
> > > > computation but just move data around, I think it could matter.
> > Certainly
> > > > there are languages with constructs to allow type wrappers at zero
> cost
> > > > (Haskell's `newtype`).
> > > >
> > > > This is all just speculation until we measure, like most of this
> > thread.
> > > >
> > > > Kenn
> > > >
> > > >
> > > >> > On Thu, Jul 27, 2017 at 11:00 AM, Thomas Groh
> > > <tg...@google.com.invalid
> > > >> >
> > > >> > wrote:
> > > >> >
> > > >> > > +1 on getting rid of setCoder; just from a Java SDK perspective,
> > my
> > > >> ideal
> > > >> > > world contains PCollections which don't have a user-visible way
> to
> > > >> mutate
> > > >> > > them.
> > > >> > >
> > > >> > > My preference would be to use TypeDescriptors everywhere within
> > > >> Pipeline
> > > >> > > construction (where possible), and utilize the CoderRegistry
> > > >> everywhere
> > > >> > to
> > > >> > > actually extract the appropriate type. The unfortunate
> difficulty
> > of
> > > >> > having
> > > >> > > to encode a union type and the lack of variable-length generics
> > does
> > > >> > > complicate that. We could consider some way of constructing
> coders
> > > in
> > > >> the
> > > >> > > registry from a collection of type descriptors (which should be
> > > >> > accessible
> > > >> > > from the point the union-type is being constructed), e.g.
> > something
> > > >> like
> > > >> > > `getCoder(TypeDescriptor output, TypeDescriptor... components)`
> -
> > > that
> > > >> > does
> > > >> > > only permit a single flat level (but since this is being invoked
> > by
> > > >> the
> > > >> > SDK
> > > >> > > during construction it could also pass Coder...).
> > > >> > >
> > > >> > >
> > > >> > >
> > > >> > > On Thu, Jul 27, 2017 at 10:22 AM, Robert Bradshaw <
> > > >> > > rober...@google.com.invalid> wrote:
> > > >> > >
> > > >> > > > On Thu, Jul 27, 2017 at 10:04 AM, Kenneth Knowles
> > > >> > > > <k...@google.com.invalid> wrote:
> > > >> > > > > On Thu, Jul 27, 2017 at 2:22 AM, Lukasz Cwik
> > > >> > <lc...@google.com.invalid
> > > >> > > >
> > > >> > > > > wrote:
> > > >> > > > >>
> > > >> > > > >> Ken/Robert, I believe users will want the ability to set
> the
> > > >> output
> > > >> > > > coder
> > > >> > > > >> because coders may have intrinsic properties where the type
> > > isn't
> > > >> > > enough
> > > >> > > > >> information to fully specify what I want as a user. Some
> > cases
> > > I
> > > >> can
> > > >> > > see
> > > >> > > > >> are:
> > > >> > > > >> 1) I have a cheap and fast non-deterministic coder but a
> > > >> different
> > > >> > > > slower
> > > >> > > > >> coder when I want to use it as the key to a GBK, For
> example
> > > >> with a
> > > >> > > set
> > > >> > > > >> coder, it would need to consistently order the values of
> the
> > > set
> > > >> > when
> > > >> > > > used
> > > >> > > > >> as the key.
> > > >> > > > >> 2) I know a property of the data which allows me to have a
> > > >> cheaper
> > > >> > > > >> encoding. Imagine I know that all the strings have a common
> > > >> prefix
> > > >> > or
> > > >> > > > >> integers that are in a certain range, or that a matrix is
> > > >> > > sparse/dense.
> > > >> > > > Not
> > > >> > > > >> all PCollections of strings / integers / matrices in the
> > > pipeline
> > > >> > will
> > > >> > > > have
> > > >> > > > >> this property, just some.
> > > >> > > > >> 3) Sorting comes up occasionally, traditionally in Google
> > this
> > > >> was
> > > >> > > done
> > > >> > > > by
> > > >> > > > >> sorting the encoded version of the object lexicographically
> > > >> during a
> > > >> > > > GBK.
> > > >> > > > >> There are good lexicographical byte representations for
> ASCII
> > > >> > strings,
> > > >> > > > >> integers, and for some IEEE number representations which
> > could
> > > be
> > > >> > done
> > > >> > > > by
> > > >> > > > >> the use of a special coder.
> > > >> > > > >>
> > > >> > > > >
> > > >> > > > > Items (1) and (3) do not require special knowledge from the
> > > user.
> > > >> > They
> > > >> > > > are
> > > >> > > > > easily observed properties of a pipeline. My proposal
> included
> > > >> full
> > > >> > > > > automation for both. The suggestion is new methods
> > > >> > > > > .getDeterministicCoder(TypeDescriptor) and
> > > >> > > > > .getLexicographicCoder(TypeDescriptor).
> > > >> > > >
> > > >> > > > Completely agree--usecases (1) and (3) are an indirect use of
> > > Coders
> > > >> > > > that are used to achieve an effect that would be better
> > expressed
> > > >> > > > directly.
> > > >> > > >
> > > >> > > > > (2) is an interesting hypothetical for massive scale where
> > tiny
> > > >> > > > incremental
> > > >> > > > > optimization represents a lot of cost _and_ your data has
> > > >> sufficient
> > > >> > > > > structure to realize a benefit _and_ it needs to be
> pinpointed
> > > to
> > > >> > just
> > > >> > > > some
> > > >> > > > > PCollections. I think our experience with coders so far is
> > that
> > > >> their
> > > >> > > > > existence is almost entirely negative. It would be nice to
> > > support
> > > >> > this
> > > >> > > > > vanishingly rare case without inflicting a terrible pain
> point
> > > on
> > > >> the
> > > >> > > > model
> > > >> > > > > and all other users.
> > > >> > > >
> > > >> > > > (2) is not just about cheapness, sometimes there's other
> > structure
> > > >> in
> > > >> > > > the data we can leverage. Consider the UnionCoder used in
> > > >> > > > CoGBK--RawUnionValue has an integer value that specifies
> > indicates
> > > >> the
> > > >> > > > type of it's raw Object field. Unless we want to extend the
> type
> > > >> > > > language, there's not a sufficient type descriptor that can be
> > > used
> > > >> to
> > > >> > > > infer the coder. I'm dubious going down the road of adding
> > special
> > > >> > > > cases is the right thing here.
> > > >> > > >
> > > >> > > > > For example, in those cases you could encode in your
> > > >> > > > > DoFn so the type descriptor would just be byte[].
> > > >> > > >
> > > >> > > > As well as being an extremely cumbersome API, this would incur
> > the
> > > >> > > > cost of coding/decoding at that DoFn boundary even if it is
> > fused
> > > >> > > > away.
> > > >> > > >
> > > >> > > > >> On Thu, Jul 27, 2017 at 1:34 AM, Jean-Baptiste Onofré <
> > > >> > > j...@nanthrax.net>
> > > >> > > > >> wrote:
> > > >> > > > >>
> > > >> > > > >> > Hi,
> > > >> > > > >> >
> > > >> > > > >> > That's an interesting thread and I was wondering the
> > > >> relationship
> > > >> > > > between
> > > >> > > > >> > type descriptor and coder for a while ;)
> > > >> > > > >> >
> > > >> > > > >> > Today, in a PCollection, we can set the coder and we also
> > > have
> > > >> a
> > > >> > > > >> > getTypeDescriptor(). It sounds weird to me: it should be
> > one
> > > or
> > > >> > the
> > > >> > > > >> other.
> > > >> > > > >> >
> > > >> > > > >> > Basically, if the Coder is not used to define the type,
> > > than, I
> > > >> > > fully
> > > >> > > > >> > agree with Eugene.
> > > >> > > > >> >
> > > >> > > > >> > Basically, the PCollection should define only the type
> > > >> descriptor,
> > > >> > > not
> > > >> > > > >> the
> > > >> > > > >> > coder by itself: the coder can be found using the type
> > > >> descriptor.
> > > >> > > > >> >
> > > >> > > > >> > With both coder and type descriptor on the PCollection,
> it
> > > >> sounds
> > > >> > a
> > > >> > > > big
> > > >> > > > >> > "decoupled" to me and it would be possible to have a
> coder
> > on
> > > >> the
> > > >> > > > >> > PCollection that doesn't match the type descriptor.
> > > >> > > > >> >
> > > >> > > > >> > I think PCollection type descriptor should be defined,
> and
> > > the
> > > >> > coder
> > > >> > > > >> > should be implicit based on this type descriptor.
> > > >> > > > >> >
> > > >> > > > >> > Thoughts ?
> > > >> > > > >> >
> > > >> > > > >> > Regards
> > > >> > > > >> > JB
> > > >> > > > >> >
> > > >> > > > >> >
> > > >> > > > >> > On 07/26/2017 05:25 AM, Eugene Kirpichov wrote:
> > > >> > > > >> >
> > > >> > > > >> >> Hello,
> > > >> > > > >> >>
> > > >> > > > >> >> I've worked on a few different things recently and ran
> > > >> repeatedly
> > > >> > > > into
> > > >> > > > >> the
> > > >> > > > >> >> same issue: that we do not have clear guidance on who
> > should
> > > >> set
> > > >> > > the
> > > >> > > > >> Coder
> > > >> > > > >> >> on a PCollection: is it responsibility of the PTransform
> > > that
> > > >> > > outputs
> > > >> > > > >> it,
> > > >> > > > >> >> or is it responsibility of the user, or is it sometimes
> > one
> > > >> and
> > > >> > > > >> sometimes
> > > >> > > > >> >> the other?
> > > >> > > > >> >>
> > > >> > > > >> >> I believe that the answer is "it's responsibility of the
> > > >> > transform"
> > > >> > > > and
> > > >> > > > >> >> moreover that  ideally PCollection.setCoder() should not
> > > >> exist.
> > > >> > > > Instead:
> > > >> > > > >> >>
> > > >> > > > >> >> - Require that all transforms set a Coder on the
> > > PCollection's
> > > >> > they
> > > >> > > > >> >> produce
> > > >> > > > >> >> - i.e. it should never be responsibility of the user to
> > "fix
> > > >> up"
> > > >> > a
> > > >> > > > coder
> > > >> > > > >> >> on
> > > >> > > > >> >> a PCollection produced by a transform.
> > > >> > > > >> >>
> > > >> > > > >> >> - Since all transforms are composed of primitive
> > transforms,
> > > >> > saying
> > > >> > > > >> >> "transforms must set a Coder" means simply that all
> > > >> *primitive*
> > > >> > > > >> transforms
> > > >> > > > >> >> must set a Coder on their output.
> > > >> > > > >> >>
> > > >> > > > >> >> - In some cases, a primitive PTransform currently
> doesn't
> > > have
> > > >> > > enough
> > > >> > > > >> >> information to infer a coder for its output collection -
> > > e.g.
> > > >> > > > >> >> ParDo.of(DoFn<InputT, OutputT>) might be unable to
> infer a
> > > >> coder
> > > >> > > for
> > > >> > > > >> >> OutputT. In that case such transforms should allow the
> > user
> > > to
> > > >> > > > provide a
> > > >> > > > >> >> coder: ParDo.of(DoFn).withOutputCoder(...) [note that
> > this
> > > >> > differs
> > > >> > > > from
> > > >> > > > >> >> requiring the user to set a coder on the resulting
> > > collection]
> > > >> > > > >> >>
> > > >> > > > >> >> - Corollary: composite transforms need to only configure
> > > their
> > > >> > > > primitive
> > > >> > > > >> >> transforms (and composite sub-transforms) properly, and
> > give
> > > >> > them a
> > > >> > > > >> Coder
> > > >> > > > >> >> if needed.
> > > >> > > > >> >>
> > > >> > > > >> >> - Corollary: a PTransform with type parameters <FooT,
> > BarT,
> > > >> ...>
> > > >> > > > needs
> > > >> > > > >> to
> > > >> > > > >> >> be configurable with coders for all of these, because
> the
> > > >> > > > implementation
> > > >> > > > >> >> of
> > > >> > > > >> >> the transform may change and it may introduce
> intermediate
> > > >> > > > collections
> > > >> > > > >> >> involving these types. However, in many cases, some of
> > these
> > > >> type
> > > >> > > > >> >> parameters appear in the type of the transform's input,
> > > e.g. a
> > > >> > > > >> >> PTransform<PCollection<KV<FooT, BarT>>,
> > PCollection<MooT>>
> > > >> will
> > > >> > > > always
> > > >> > > > >> be
> > > >> > > > >> >> able to extract the coders for FooT and BarT from the
> > input
> > > >> > > > PCollection,
> > > >> > > > >> >> so
> > > >> > > > >> >> the user does not need to provide them. However, a coder
> > for
> > > >> BarT
> > > >> > > > must
> > > >> > > > >> be
> > > >> > > > >> >> provided. I think in most cases the transform needs to
> be
> > > >> > > > configurable
> > > >> > > > >> >> only
> > > >> > > > >> >> with coders for its output.
> > > >> > > > >> >>
> > > >> > > > >> >> Here's a smooth migration path to accomplish the above:
> > > >> > > > >> >> - Make PCollection.createPrimitiveOutputInternal()
> take a
> > > >> Coder.
> > > >> > > > >> >> - Make all primitive transforms optionally configurable
> > > with a
> > > >> > > coder
> > > >> > > > for
> > > >> > > > >> >> their outputs, such as ParDo.of(DoFn).
> withOutputCoder().
> > > >> > > > >> >> - By using the above, make all composite transforms
> > shipped
> > > >> with
> > > >> > > the
> > > >> > > > SDK
> > > >> > > > >> >> set a Coder on the collections they produce; in some
> > cases,
> > > >> this
> > > >> > > will
> > > >> > > > >> >> require adding a withSomethingCoder() option to the
> > > transform
> > > >> and
> > > >> > > > >> >> propagating that coder to its sub-transforms. If the
> > option
> > > is
> > > >> > > unset,
> > > >> > > > >> >> that's fine for now.
> > > >> > > > >> >> - As a result of the above, get rid of all setCoder()
> > calls
> > > in
> > > >> > the
> > > >> > > > Beam
> > > >> > > > >> >> repo. The call will still be there, but it will just not
> > be
> > > >> used
> > > >> > > > >> anywhere
> > > >> > > > >> >> in the SDK or examples, and we can mark it deprecated.
> > > >> > > > >> >> - Add guidance to PTransform Style Guide in line with
> the
> > > >> above
> > > >> > > > >> >>
> > > >> > > > >> >> Does this sound like a good idea? I'm not sure how
> urgent
> > it
> > > >> > would
> > > >> > > > be to
> > > >> > > > >> >> actually do this, but I'd like to know whether people
> > agree
> > > >> that
> > > >> > > this
> > > >> > > > >> is a
> > > >> > > > >> >> good goal in general.
> > > >> > > > >> >>
> > > >> > > > >> >>
> > > >> > > > >> > --
> > > >> > > > >> > Jean-Baptiste Onofré
> > > >> > > > >> > jbono...@apache.org
> > > >> > > > >> > http://blog.nanthrax.net
> > > >> > > > >> > Talend - http://www.talend.com
> > > >> > > > >> >
> > > >> > > > >>
> > > >> > > >
> > > >> > >
> > > >> >
> > > >>
> > > >
> > > >
> > >
> >
>

Reply via email to