#map0 = (d0, d1, d2) -> (d2 floordiv 8, d0, d1, d2 mod 8)
%t1 = alloc() : memref<12x12x16xf32>
%t2 = alloc() : memref<12x12x16xf32, #map0>
affine.for %i = 0 to 12 {
affine.for %j = 0 to 12 {
affine.for %k = 0 to 16 {
%1 = affine.load %t1[%i, %j, %k]
affine.store %1 %t2[%i, %j, %k]
}
}
}
affine.for %k = 0 to 2 {
affine.for %i = 0 to 12 {
affine.for %j = 0 to 12 {
affine.for %k_inner = 0 to 8 {
%2 = affine.load %t2[%i, %j, %k * 8 + %k_inner]
}
}
}
}--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/7cba604a-b253-4009-b540-817782ff7906%40tensorflow.org.
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/7696e6ab-b49f-4c43-85ef-c9e707082286%40tensorflow.org.
Thanks Jun,I agree that AffineMap is very expressive for specifying layout. The issue is that we would like to pass MemRefs/Buffers between affine and non-affine regions of code, and AffineMap is an affine dialect construct. Likely the layout will being attribute and you can use AffineMap to express layout in affine
regions if you like.Agree about the composition of affine.load/affine.store affine maps and layout. Forcing affine.load and affine.store to take affine maps by construction, will avoid the need to always compose the load/store affine maps when you want to evaluate that composition.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
I think that AffineMap is expressive to describe the layout.For example, there is a Tensor, whose layout is HWC. Then I want to do data tiling of this Tensor, it will be changed to CHW8c.#map0 = (d0, d1, d2) -> (d2 floordiv 8, d0, d1, d2 mod 8)
%t1 = alloc() : memref<12x12x16xf32>
%t2 = alloc() : memref<12x12x16xf32, #map0>
affine.for %i = 0 to 12 {
affine.for %j = 0 to 12 {
affine.for %k = 0 to 16 {
%1 = affine.load %t1[%i, %j, %k]
affine.store %1 %t2[%i, %j, %k]
}
}
}%t1 is the original data, and %t2 is the data after tiling.When I pass the same logic index, it will generate different memory address.We can also do loop tiling at the same time,affine.for %k = 0 to 2 {
affine.for %i = 0 to 12 {
affine.for %j = 0 to 12 {
affine.for %k_inner = 0 to 8 {
%2 = affine.load %t2[%i, %j, %k * 8 + %k_inner]
}
}
}
}
So there will be two AffineMaps, one is in affine.load, the other is in memref. These two AffineMaps could be composed, and then generate the right address in physical memory.The layout has a close relation with data tiling and loop tiling. It's better to give a whole picture to the community.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/9e738334-f5e0-4bda-9e80-7496e54412a4%40tensorflow.org.
Thanks Uday. I think that this is motivated in part, by part of the motivation for creating affine.load/store (so that std.load/store do not always have to deal with the affine constraint), and we'd like the memref/buffer type to be passed freely between non-affine and affine regions. Do you have a use case for using an affine map in a non-affine region?
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/9e738334-f5e0-4bda-9e80-7496e54412a4%40tensorflow.org.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/8d152d13-00c8-450c-a71d-3df94c1ed550%40tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/CAPL655gnaHDJp8NdK%2BvGaVFAfLruq-Cei8d1Dc8ZHRmHXTrvKw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/8d152d13-00c8-450c-a71d-3df94c1ed550%40tensorflow.org.
---- Alex--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/CAPL655gnaHDJp8NdK%2BvGaVFAfLruq-Cei8d1Dc8ZHRmHXTrvKw%40mail.gmail.com.
---- Alex
IMO, "buffer" sounds like it implies ownership/exclusiveness semantics. That is, having two values of type "buffer<???>" sounds like a guarantee that they are different buffers and don't alias, which is not the case with memrefs currently. I know this isn't true in many programming models, but it is often the case in ML-ish libraries. Memref, on the other hand, implies it's a reference, although I'm not a fan of the name.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/8d152d13-00c8-450c-a71d-3df94c1ed550%40tensorflow.org.
---- Alex--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/CAPL655gnaHDJp8NdK%2BvGaVFAfLruq-Cei8d1Dc8ZHRmHXTrvKw%40mail.gmail.com.
---- Alex
On Monday, July 8, 2019 at 1:59:47 PM UTC+5:30, Alex Zinenko wrote:IMO, "buffer" sounds like it implies ownership/exclusiveness semantics. That is, having two values of type "buffer<???>" sounds like a guarantee that they are different buffers and don't alias, which is not the case with memrefs currently. I know this isn't true in many programming models, but it is often the case in ML-ish libraries. Memref, on the other hand, implies it's a reference, although I'm not a fan of the name.+1 to retaining memref's, although note that if you do have a buffer type, they could still alias (for eg. when the same buffer SSA value is passed via two different arguments of the same function call).But I would still argue against these 1-d buffer (pointer + offset) abstractions in MLIR proper because:
1) I think MLIR is a lot about preserving the multi-dimensional nature of data whenever possible, and adding such pointer + offset abstractions in the core type system is often a liability because users could generate these instead of true multi-dimensional memref's. As a result, you get lower level representations instead of higher level ones too early, and you are back to the issues one faces with IRs like LLVM while performing high-level or mid-level analyses/transforms.
2) You could always have lower-level dialects have such buffer abstractions (for eg. the LLVM dialect could have a buffer + offset abstraction that readily lowers to GEPs). This also makes sure that such things get generated when everything else (surrounding IR) is also low level, i.e., lowering happens in a coordinated way. While one could say that MLIR allows mixing arbitrary dialect ops and that everything being associated with some dialect is modular, it is also a hindrance for passes/utilities to have to deal with high and low level versions of the same thing from different dialects.
Coming back, I still don't see the motivation behind changing the memref type to a 1-d buffer with size. One could add such abstractions separately, but it looks like those are still better done in specific low level dialects instead of in MLIR's type system.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/83bb23c6-88ea-43d8-92fa-45957ef035c2%40tensorflow.org.
On Wed, Jul 10, 2019 at 7:41 AM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Monday, July 8, 2019 at 1:59:47 PM UTC+5:30, Alex Zinenko wrote:IMO, "buffer" sounds like it implies ownership/exclusiveness semantics. That is, having two values of type "buffer<???>" sounds like a guarantee that they are different buffers and don't alias, which is not the case with memrefs currently. I know this isn't true in many programming models, but it is often the case in ML-ish libraries. Memref, on the other hand, implies it's a reference, although I'm not a fan of the name.+1 to retaining memref's, although note that if you do have a buffer type, they could still alias (for eg. when the same buffer SSA value is passed via two different arguments of the same function call).But I would still argue against these 1-d buffer (pointer + offset) abstractions in MLIR proper because:These days, you need to define what "MLIR proper" means. MLIR's IR is currently a set of dialects containing operations, attributes and types. There are so called "standard types", which are expected to belong to the standard dialect after a refactoring. The only difference between those and dialect-defined types is that they don't have to be prefixed with a bang. (Note that the same is true for ops in the standard dialect that are allowed to elide the std. prefix.) I would strongly support that some MLIR dialect that lives in the MLIR code base (i.e. tensorflow/mlir as opposed to tensorflow/tensorflow/compiler) has a sized buffer abstraction. Whether it is the standard dialect or not is a different discussion. At this point, "standard" does not mean anything to me.1) I think MLIR is a lot about preserving the multi-dimensional nature of data whenever possible, and adding such pointer + offset abstractions in the core type system is often a liability because users could generate these instead of true multi-dimensional memref's. As a result, you get lower level representations instead of higher level ones too early, and you are back to the issues one faces with IRs like LLVM while performing high-level or mid-level analyses/transforms.I fully agree with the danger of having lower-level abstractions available and being used directly instead of higher-level abstractions. I do however think that it is an organizational problem, not a technical problem. The LLVM dialect is available and literally nothing prevents users from targeting it directly instead of standard/affine. And people actually did go directly to LLVM (although that code actually reuses the lowering functions, it never materializes the intermediate steps in the IR). We should just explain properly why targeting a low-level dialect directly may be a bad idea. Sometimes it is not, when the user upstream knows what they are doing and by lowreing early they can actually tell MLIR not to touch their code.Depending on the interface points with an external representation, a 1D sized buffer may be the right abstraction, if followed by some "view" operation that reconstructs the multidimensional nature of the underlying data. For example, if you are willing to interoperate with C, you can accept a bare pointer and view it as a multi-dimensional array with layouts internally. So it's not a matter of having an abstraction, it's a matter of using it judiciously.2) You could always have lower-level dialects have such buffer abstractions (for eg. the LLVM dialect could have a buffer + offset abstraction that readily lowers to GEPs). This also makes sure that such things get generated when everything else (surrounding IR) is also low level, i.e., lowering happens in a coordinated way. While one could say that MLIR allows mixing arbitrary dialect ops and that everything being associated with some dialect is modular, it is also a hindrance for passes/utilities to have to deal with high and low level versions of the same thing from different dialects.The design rationale of the LLVM dialect is to reflect the actual LLVM IR as closely as possible. LLVM IR does not have a sized buffer abstraction (it does have fixed-size arrays though), so neither should the LLVM dialect.I am not convinced that buffers should appear very late. If we follow XLA's steps to go from tensor-level operations to scalar operations, buffer allocation happens before loops are generated.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/83bb23c6-88ea-43d8-92fa-45957ef035c2%40tensorflow.org.
---- Alex
On Wednesday, July 10, 2019 at 2:05:02 PM UTC+5:30, Alex Zinenko wrote:On Wed, Jul 10, 2019 at 7:41 AM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Monday, July 8, 2019 at 1:59:47 PM UTC+5:30, Alex Zinenko wrote:IMO, "buffer" sounds like it implies ownership/exclusiveness semantics. That is, having two values of type "buffer<???>" sounds like a guarantee that they are different buffers and don't alias, which is not the case with memrefs currently. I know this isn't true in many programming models, but it is often the case in ML-ish libraries. Memref, on the other hand, implies it's a reference, although I'm not a fan of the name.+1 to retaining memref's, although note that if you do have a buffer type, they could still alias (for eg. when the same buffer SSA value is passed via two different arguments of the same function call).But I would still argue against these 1-d buffer (pointer + offset) abstractions in MLIR proper because:These days, you need to define what "MLIR proper" means. MLIR's IR is currently a set of dialects containing operations, attributes and types. There are so called "standard types", which are expected to belong to the standard dialect after a refactoring. The only difference between those and dialect-defined types is that they don't have to be prefixed with a bang. (Note that the same is true for ops in the standard dialect that are allowed to elide the std. prefix.) I would strongly support that some MLIR dialect that lives in the MLIR code base (i.e. tensorflow/mlir as opposed to tensorflow/tensorflow/compiler) has a sized buffer abstraction. Whether it is the standard dialect or not is a different discussion. At this point, "standard" does not mean anything to me.1) I think MLIR is a lot about preserving the multi-dimensional nature of data whenever possible, and adding such pointer + offset abstractions in the core type system is often a liability because users could generate these instead of true multi-dimensional memref's. As a result, you get lower level representations instead of higher level ones too early, and you are back to the issues one faces with IRs like LLVM while performing high-level or mid-level analyses/transforms.I fully agree with the danger of having lower-level abstractions available and being used directly instead of higher-level abstractions. I do however think that it is an organizational problem, not a technical problem. The LLVM dialect is available and literally nothing prevents users from targeting it directly instead of standard/affine. And people actually did go directly to LLVM (although that code actually reuses the lowering functions, it never materializes the intermediate steps in the IR). We should just explain properly why targeting a low-level dialect directly may be a bad idea. Sometimes it is not, when the user upstream knows what they are doing and by lowreing early they can actually tell MLIR not to touch their code.Depending on the interface points with an external representation, a 1D sized buffer may be the right abstraction, if followed by some "view" operation that reconstructs the multidimensional nature of the underlying data. For example, if you are willing to interoperate with C, you can accept a bare pointer and view it as a multi-dimensional array with layouts internally. So it's not a matter of having an abstraction, it's a matter of using it judiciously.2) You could always have lower-level dialects have such buffer abstractions (for eg. the LLVM dialect could have a buffer + offset abstraction that readily lowers to GEPs). This also makes sure that such things get generated when everything else (surrounding IR) is also low level, i.e., lowering happens in a coordinated way. While one could say that MLIR allows mixing arbitrary dialect ops and that everything being associated with some dialect is modular, it is also a hindrance for passes/utilities to have to deal with high and low level versions of the same thing from different dialects.The design rationale of the LLVM dialect is to reflect the actual LLVM IR as closely as possible. LLVM IR does not have a sized buffer abstraction (it does have fixed-size arrays though), so neither should the LLVM dialect.I am not convinced that buffers should appear very late. If we follow XLA's steps to go from tensor-level operations to scalar operations, buffer allocation happens before loops are generated.But buffer allocation and reuse can already be done with the current multidimensional memref's and views. It's still not clear why one needs a memref to be a 1-d buffer + size abstraction in order to do allocation and reuse. What is really missing is the equivalent of a "pointer to the underlying buffer" abstraction that is desired when mapping to calls to say external tuned libraries or for FFI at the mid-level or at the high-level of MLIR (when you don't want to introduce lower level dialect abstractions in the IR), or in scenarios like the ones Nagy Mostafa and you mention in two other threads respectively. And these appear to be better addressed by introducing a 'buf' operation on a memref that returns a buffer type (which is elemental type-erased like you asked for). This would be very different from the proposal in the OP of changing the memref type to make it a sized 1-d buffer because with the latter, you are also incidentally (and unintentionally?) providing a user a way to deference a 1-d thing, which really isn't needed and which is an extra alias. Wasn't your intention to get access to the underlying buffer as opposed to use it for indexing?
OTOH, having a 'buf' operation return a buffer type given the current memref operand means:(1) one still can't deference it, but is still able to use it with an FFI, as an argument to BLAS calls etc., which is very useful during early stages of lowering, (the type will readily map to void *)(2) the only way to construct such buffer types would be by using a 'buf' operation on an existing memref that is of the desired dimensionality.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/d7c3e5d9-562a-4b9b-aec9-8c7090a33a31%40tensorflow.org.
On Wed, Jul 17, 2019 at 3:07 PM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Wednesday, July 10, 2019 at 2:05:02 PM UTC+5:30, Alex Zinenko wrote:On Wed, Jul 10, 2019 at 7:41 AM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
On Monday, July 8, 2019 at 1:59:47 PM UTC+5:30, Alex Zinenko wrote:IMO, "buffer" sounds like it implies ownership/exclusiveness semantics. That is, having two values of type "buffer<???>" sounds like a guarantee that they are different buffers and don't alias, which is not the case with memrefs currently. I know this isn't true in many programming models, but it is often the case in ML-ish libraries. Memref, on the other hand, implies it's a reference, although I'm not a fan of the name.+1 to retaining memref's, although note that if you do have a buffer type, they could still alias (for eg. when the same buffer SSA value is passed via two different arguments of the same function call).But I would still argue against these 1-d buffer (pointer + offset) abstractions in MLIR proper because:These days, you need to define what "MLIR proper" means. MLIR's IR is currently a set of dialects containing operations, attributes and types. There are so called "standard types", which are expected to belong to the standard dialect after a refactoring. The only difference between those and dialect-defined types is that they don't have to be prefixed with a bang. (Note that the same is true for ops in the standard dialect that are allowed to elide the std. prefix.) I would strongly support that some MLIR dialect that lives in the MLIR code base (i.e. tensorflow/mlir as opposed to tensorflow/tensorflow/compiler) has a sized buffer abstraction. Whether it is the standard dialect or not is a different discussion. At this point, "standard" does not mean anything to me.1) I think MLIR is a lot about preserving the multi-dimensional nature of data whenever possible, and adding such pointer + offset abstractions in the core type system is often a liability because users could generate these instead of true multi-dimensional memref's. As a result, you get lower level representations instead of higher level ones too early, and you are back to the issues one faces with IRs like LLVM while performing high-level or mid-level analyses/transforms.I fully agree with the danger of having lower-level abstractions available and being used directly instead of higher-level abstractions. I do however think that it is an organizational problem, not a technical problem. The LLVM dialect is available and literally nothing prevents users from targeting it directly instead of standard/affine. And people actually did go directly to LLVM (although that code actually reuses the lowering functions, it never materializes the intermediate steps in the IR). We should just explain properly why targeting a low-level dialect directly may be a bad idea. Sometimes it is not, when the user upstream knows what they are doing and by lowreing early they can actually tell MLIR not to touch their code.Depending on the interface points with an external representation, a 1D sized buffer may be the right abstraction, if followed by some "view" operation that reconstructs the multidimensional nature of the underlying data. For example, if you are willing to interoperate with C, you can accept a bare pointer and view it as a multi-dimensional array with layouts internally. So it's not a matter of having an abstraction, it's a matter of using it judiciously.2) You could always have lower-level dialects have such buffer abstractions (for eg. the LLVM dialect could have a buffer + offset abstraction that readily lowers to GEPs). This also makes sure that such things get generated when everything else (surrounding IR) is also low level, i.e., lowering happens in a coordinated way. While one could say that MLIR allows mixing arbitrary dialect ops and that everything being associated with some dialect is modular, it is also a hindrance for passes/utilities to have to deal with high and low level versions of the same thing from different dialects.The design rationale of the LLVM dialect is to reflect the actual LLVM IR as closely as possible. LLVM IR does not have a sized buffer abstraction (it does have fixed-size arrays though), so neither should the LLVM dialect.I am not convinced that buffers should appear very late. If we follow XLA's steps to go from tensor-level operations to scalar operations, buffer allocation happens before loops are generated.But buffer allocation and reuse can already be done with the current multidimensional memref's and views. It's still not clear why one needs a memref to be a 1-d buffer + size abstraction in order to do allocation and reuse. What is really missing is the equivalent of a "pointer to the underlying buffer" abstraction that is desired when mapping to calls to say external tuned libraries or for FFI at the mid-level or at the high-level of MLIR (when you don't want to introduce lower level dialect abstractions in the IR), or in scenarios like the ones Nagy Mostafa and you mention in two other threads respectively. And these appear to be better addressed by introducing a 'buf' operation on a memref that returns a buffer type (which is elemental type-erased like you asked for). This would be very different from the proposal in the OP of changing the memref type to make it a sized 1-d buffer because with the latter, you are also incidentally (and unintentionally?) providing a user a way to deference a 1-d thing, which really isn't needed and which is an extra alias. Wasn't your intention to get access to the underlying buffer as opposed to use it for indexing?I think there is a bit of terminology confusion between different people in different threads. What you describe above is very close to what I had in mind. One of the design points I want to make is to separate allocation abstraction (I call this a buffer) from indexing abstraction (I call this a view), but this is not fully decided yet. Currently, memrefs are both. The proposition (2) is the original email is to make memref what I call a buffer, and create a view type. What you seem to be proposing is to create a buffer type, and make memref what I call a view. It's essentially the same thing except for naming :) I think it does make sense to have both a view-creation and an underlying-buffer-extraction operations to go between buffers and views, where the latter is the "buf" operation you are proposing.
OTOH, having a 'buf' operation return a buffer type given the current memref operand means:(1) one still can't deference it, but is still able to use it with an FFI, as an argument to BLAS calls etc., which is very useful during early stages of lowering, (the type will readily map to void *)(2) the only way to construct such buffer types would be by using a 'buf' operation on an existing memref that is of the desired dimensionality.This means the lowering starts with functions accepting memrefs, which is not always desirable. I have a use case where I would want to have something like:@func compute(%inputs: !buffer<i8>, %output: !buffer<i8>, %temp: !buffer<i8>) {%a = "slice"(%inputs) {offset = 1024, shape=[32,32], layout="WH", type="f32"} : (!buffer<i8>) -> memref<?x?xf32>
%b = "slice"(%inputs) {offset = 0, shape=[32,32], layout="HW", type="f32"} : (!buffer<i8>) -> memref<?x?xf32, (i,j)->(j,i)>
%c = "slice"(%temp) {offset = 0, shape=[32,32], layout="WH", type="f32"} : (!buffer<i8>) -> memref<?x?xf32>
%d = "slice"(%outputs) {offset = 0, shape=[32,32], layout="WH", type="f32"} : (!buffer<i8>) -> memref<?x?xf32>
"layer.fc"(%a, %b, %c) // %c is the output
"layer.relu(%c) // inplace
"layer.fc"(%a, %c, %d) // %d is the output
"layer.relu"(%c) // inplace
return
}to delegate buffer assignment to the framework using MLIR. It feels conceptually cleaner if the framework passes buffers to the function, rather than memrefs from which the function should recover the buffers. This is especially true for various temporary or scratchpad buffers when something like TF captures all the memory, where implementation function essentially gets a pointer to a temporary buffer whether it needs it or not and is allowed to do whatever it wants with it.
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/f5ffe728-00f8-43e5-af7f-d91f27b2d303%40tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/CAFfp4mN0-%2B%2BCEj8SH9sCgOzGF4ct1FJt%2BUAGUCHC_pePJE4Dbg%40mail.gmail.com.
With the proposal B, my example would look likefunc @compute(%inputs: memref<?xi8>, %outputs: memref<?xi8>, %temp: memref<?xi8>) {%input_buffer = "buf"(%inputs) : (memref<?xi8>) -> !buffer<i8>
%a = "slice"(%input_buffer) {offset = 1024, shape=[32,32], layout="WH", type="f32"} : (!buffer<i8>) -> memref<?x?xf32>
/*...*/
}
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/f5ffe728-00f8-43e5-af7f-d91f27b2d303%40tensorflow.org.
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/CAFfp4mN0-%2B%2BCEj8SH9sCgOzGF4ct1FJt%2BUAGUCHC_pePJE4Dbg%40mail.gmail.com.
---- Alex
On Wednesday, July 24, 2019 at 2:28:51 PM UTC+5:30, Alex Zinenko wrote:With the proposal B, my example would look likefunc @compute(%inputs: memref<?xi8>, %outputs: memref<?xi8>, %temp: memref<?xi8>) {%input_buffer = "buf"(%inputs) : (memref<?xi8>) -> !buffer<i8>
%a = "slice"(%input_buffer) {offset = 1024, shape=[32,32], layout="WH", type="f32"} : (!buffer<i8>) -> memref<?x?xf32>
/*...*/
}No, with both proposals, your example would still take 'buffer' type's as inputs if you prefer that. With proposal B, you would then create the memref from the buffer where you need it. The only difference between the proposals is what alloc returns - do you want to create a buffer type each time you want to create a memref or just have the alloc return the memref you want?
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/7b634b6b-dddc-4b47-983b-ad928a2a7d80%40tensorflow.org.
Because all you would do with the buffer type in nearly all cases is to create a memref from it immediately (except when interacting with external interfaces). And for the latter, you can just extract the buffer type or vice versa. Is there another place where the buffer type is used as an operand?
- Uday
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/b41c3124-9379-46b7-be86-d298ea17a9be%40tensorflow.org.
What's your use case for extracting the buffer out of the memref, other than slicing the buffer differently? I don't have one so I may not be needing that operation at all.
On the other hand, having alloc return a memref creates two implicit kinds of memrefs: "allocated" memrefs that you may need to deallocate and "alias" memrefs that you don't. You can actually call dealloc on any of the aliases, freeing potentially more memory than the memref tyt pe says.
On Thu, Jul 25, 2019 at 7:54 AM 'Uday Bondhugula' via MLIR <ml...@tensorflow.org> wrote:
>If you have a buffer type anyway, and you also
>have the ability to create a memref from a >buffer, then why wouldn't alloc return a
>buffer?
Because all you would do with the buffer type in nearly all cases is to create a memref from it immediately (except when interacting with external interfaces). And for the latter, you can just extract the buffer type or vice versa. Is there another place where the buffer type is used as an operand?
- Uday
--
You received this message because you are subscribed to the Google Groups "MLIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ml...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/b41c3124-9379-46b7-be86-d298ea17a9be%40tensorflow.org.
---- Alex
To unsubscribe from this group and stop receiving emails from it, send an email to mlir+uns...@tensorflow.org.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/mlir/4ee89613-4b28-4dd1-9c32-56e73c5ed722%40tensorflow.org.