Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

symbolic_vector and symbolic_matrix ? #47

Closed
albertz opened this issue Nov 20, 2013 · 13 comments
Closed

symbolic_vector and symbolic_matrix ? #47

albertz opened this issue Nov 20, 2013 · 13 comments

Comments

@albertz
Copy link
Contributor

albertz commented Nov 20, 2013

In the doc, there is the following example:

// Instantiation of the symbolic variables
symbolic_vector<NumericT, 0> sX;
symbolic_matrix<NumericT, 1> sA;
symbolic_vector<NumericT, 2> sY;
symbolic_vector<NumericT, 3> sZ;

//Creation of the custom operation
custom_operation my_op( sX = prod(sA, inner_prod(sY, sY+sZ) * sY + sZ),
    "operation_name" );

However, I don't see those types anywhere defined in the code. So, is the doc outdated/wrong?

(A bit OT: I want to do something like this. I also asked on SO about it.)

@ptillet
Copy link
Collaborator

ptillet commented Nov 20, 2013

Hello Albert,

There was an important change in the codebase and we are working towards
the transparent integration of the kernel generator, which explains why the
code you are pointing at no longer exists...! If you plan on using
generated code, I advise you to write the operations using the viennacl
structures, and kernel generation should come later using just a
preprocessor directive. If for some reason you wish to know more about the
implementation details of the kernel generator, don't hesitate to contact
me so we can discuss in more depth about it.
On Nov 20, 2013 8:39 PM, "Albert Zeyer" notifications@github.com wrote:

In the doc, there is the following example:

// Instantiation of the symbolic variables
symbolic_vector<NumericT, 0> sX;
symbolic_matrix<NumericT, 1> sA;
symbolic_vector<NumericT, 2> sY;
symbolic_vector<NumericT, 3> sZ;

//Creation of the custom operation
custom_operation my_op( sX = prod(sA, inner_prod(sY, sY+sZ) * sY + sZ),
"operation_name" );

However, I don't see those types anywhere defined in the code. So, is the
doc outdated/wrong?

(A bit OT: I want to do something like this. I also asked on SOhttp://stackoverflow.com/questions/20096050/viennacl-do-element-wise-operation-on-vector-or-matrixabout it.)


Reply to this email directly or view it on GitHubhttps://github.com//issues/47
.

@albertz
Copy link
Contributor Author

albertz commented Nov 20, 2013

How exactly would that look like? You mean I just do

X = prod(A, inner_prod(Y, Y+Z) * Y + Z);

and via that preprocessor directive, it would automatically generate the kernel from this code?

@karlrupp
Copy link
Collaborator

Albert, have a look at the following example on how we currently interface the kernel generator:
https://github.com/viennacl/viennacl-dev/blob/master/examples/tutorial/scheduler.cpp
The reasons for this fairly low-level approach are two-fold:
a) not relying on separate symbolic_* types allows us to transparently create optimal kernels for operations defined on standard ViennaCL types (e.g. viennacl::vector<>)
b) we can later provide a powerful C-API for interfacing the kernel generator from e.g. Python
Things are still not 100% stable here, but we are about to converge to something that is really useful in practice)

@karlrupp
Copy link
Collaborator

Yes, the rationale for the refactoring explained above is to be able to generate an 'optimal' kernel for an operation such as

X = prod(A, inner_prod(Y, Y+Z) * Y + Z);

without requiring the user to write any 'extra' code.

@albertz
Copy link
Contributor Author

albertz commented Nov 20, 2013

Ah, ok! So, it would be best to just write "normal" ViennaCL code at the moment and I can expect that from this code, ViennaCL is able to generate the appropriate kernel (once the refactoring is done).

@ptillet
Copy link
Collaborator

ptillet commented Nov 20, 2013

Yes, exactly !
It's still not completely integrated, but the result should be pretty
useful (it will not only remove the temporary, but also generate
device-specific auto-tuned code). The explicit use of the generator is not
recommended, even though it's geting stable.

2013/11/20 Albert Zeyer notifications@github.com

Ah, ok! So, it would be best to just write "normal" ViennaCL code at the
moment and I can expect that from this code, ViennaCL is able to generate
the appropriate kernel (once the refactoring is done).


Reply to this email directly or view it on GitHubhttps://github.com//issues/47#issuecomment-28888783
.

@karlrupp
Copy link
Collaborator

Yes, the idea is that user code gets incrementally faster without being rewritten. :-)
The only limitation we face is that of temporary objects if executed in a loop, say:

while (1) { x = prod(A, inner_prod(y, y + z) * y + z); }

In such case it is better to explicitly create a temporary object outside the loop, so that there is no unnecessary reallocation of memory buffers:

vector u(N);
while (1) {
  u = inner_prod(y, y + z) * y + z;
  x = prod(A, u);
}

This, however, is an optimization detail which we will document in an optimization guide once the functionality is fully available.

@albertz
Copy link
Contributor Author

albertz commented Nov 20, 2013

That's pretty cool. :) When can I expect this to be ready?

@karlrupp
Copy link
Collaborator

Pfuh, now that's a really tough question now... Depends on the complexity of the operation and the degree of optimization you expect. For the element-wise operation you mentioned on SO you can already write 'standard' code right now without writing your own kernels, e.g.

vector<T> all_ones = viennacl::scalar_vector<T>(N, 1.0);
vector<T> x(N);
vector<T> y = element_div(all_ones, all_ones + element_exp(-1.0 * x));

Although this is not optimal in raw performance, it is likely that you have other, more expensive operations elsewhere, so you only want to avoid writing your own kernels.

@albertz
Copy link
Contributor Author

albertz commented Nov 20, 2013

There is no way to avoid that temporary vector all_ones? I need to execute this code pretty often for different sizes.

In Octave/Matlab, you can just do vector + 1 and it does that element wise. As well as 1 ./ vector. But there are no such operators in ViennaCL? Maybe this could be added because it would make this code both simpler and faster.

@ptillet
Copy link
Collaborator

ptillet commented Nov 20, 2013

I should mention that, when everything is integrated, there will be no
temporary (and no memory storage) for the scalar_vector<>. These kind of
operations already work in a generator-specific development branch, but
it's so experimental that I don't even dare to give its name :) For now,
I've been busy with some other projects, so I don't have time to work on
the stability of the kernel generator...

2013/11/20 Albert Zeyer notifications@github.com

There is no way to avoid that temporary vector all_ones? I need to
execute this code pretty often for different sizes.

In Octave/Matlab, you can just do vector + 1 and it does that element
wise. But there is no such operator in ViennaCL? Maybe this could be added
because it would make this code both simpler and faster.


Reply to this email directly or view it on GitHubhttps://github.com//issues/47#issuecomment-28890723
.

@karlrupp
Copy link
Collaborator

Albert: The current code base still requires the all_ones, yes. As Philippe said, it will later be possible to just pass `scalar_vector(N,1)' to the element_* functions in order to really generate the optimal (fastest) kernel (including device-specific work group sizes and the like).

@karlrupp
Copy link
Collaborator

Closing this issue now because symbolic_vector and symbolic_matrix are no longer provided.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants