JuliaIPU / IPUToolkit.jl

IPU programming in Julia
https://juliaipu.github.io/IPUToolkit.jl/
MIT License
30 stars 3 forks source link

Rework Codelet to be more similar to C++ API #9

Open vchuravy opened 1 year ago

vchuravy commented 1 year ago
struct MyVertex <: Vertex
  in::PopVec
  out::PopVec
end
function (vertex::MyVertex)()
   vertex.out .= vertex.in
end

According the the docs the ABI is:

int __runCodelet_MyVertex() {

  void *vertexPtr = __builtin_colossus_get_vertex_base();
  auto v = static_cast<MyVertex*>(vertexPtr);
  return v->compute();
}

We could codegen that __runCodlet function. @llvm.colossus.get.vertex.base() is the intrinsic to get the vector base.

The big unknown is how to do the mapping from Julia fields to input and output in the poplar graph.

There is an inspector https://docs.graphcore.ai/projects/poplar-api/en/latest/poplar/graph/VertexIntrospector.html#_CPPv4N6poplar18VertexIntrospectorE

So the question is how popc generates the mapping

vchuravy commented 1 year ago

There is a very interest method:

/**
 * Generate a string representation of a Vertex type for use by
 * poplar::Graph::addVertex().
 *
 * \param name  The name of the vertex.
 * \param args  The types of the arguments to the vertex.
 * \return      A string representation of the vertex type.
 */
template <typename... Args>
inline std::string templateVertex(const std::string &name, Args &&...args) {
  return name + templateVertexParams(true, std::forward<Args>(args)...);
}

That makes it sound like there is an extended addVertex function.

https://github.com/graphcore/tensorflow/blob/2b7af067dae32b210a8d1f053d1aec5f3722e[…]e8d/tensorflow/compiler/plugin/poplar/driver/vertex_templates.h

vchuravy commented 1 year ago

https://docs.graphcore.ai/projects/poplar-api/en/2.0.0/poplar_api.html#_CPPv4N6poplar5Graph9addVertexE10ComputeSet9StringRef8ArrayRefI14ConnectionDescE

vchuravy commented 1 year ago

So I propose the following experiment:

graph.addCodelets("vectorAdd.ll", CodeletFileType::IrSource)
vectorAddCS = graph.addComputeSet(poputil::templateVertex("VectorAdd"), args...);
giordano commented 1 year ago

For the record, I applied

diff --git a/feature_examples/poplar/advanced_example/Makefile b/feature_examples/poplar/advanced_example/Makefile
index b899c2f..1d59c1b 100644
--- a/feature_examples/poplar/advanced_example/Makefile
+++ b/feature_examples/poplar/advanced_example/Makefile
@@ -1,12 +1,15 @@
 CC = g++

-all: codelets.gp example
+all: example

 codelets.gp: codelets.cpp
-   popc codelets.cpp -o codelets.gp
+   popc $^ -o $@

-example: utils.h main.cpp
-   $(CC) --std=c++11 main.cpp -o example -lpoplar -lpopops -lboost_program_options
+codelets.ll: codelets.cpp
+   popc --emit-llvm -target ipu2 $^ -o $@
+
+example: main.cpp utils.h codelets.ll
+   $(CC) --std=c++11 $< -o $@ -lpoplar -lpopops -lboost_program_options

 clean:
-   rm codelets.gp example
+   rm -f codelets.ll codelets.gp example
diff --git a/feature_examples/poplar/advanced_example/main.cpp b/feature_examples/poplar/advanced_example/main.cpp
index 505fe38..dfe540d 100644
--- a/feature_examples/poplar/advanced_example/main.cpp
+++ b/feature_examples/poplar/advanced_example/main.cpp
@@ -39,7 +39,7 @@ buildGraphAndPrograms(poplar::Graph &g, const utils::Options &options) {
   // Before we can add a custom vertex to the graph we need to load its
   // code. NOTE: .gp files are precompiled codelets but we could also
   // have loaded and compiled source directly here:
-  g.addCodelets("codelets.gp"); // g.addCodelets("codelets.cpp");
+  g.addCodelets("codelets.ll"); // g.addCodelets("codelets.cpp");
   auto v = g.addVertex(cs1, "VectorAdd");

   // Vertices must also be mapped to tiles. This computation will

to https://github.com/graphcore/tutorials/tree/b7ffa4de24e07efbeda2e3241ea46d20fa119b84, and ran

make && ./example

in feature_examples/poplar/advanced_example, but I got

Using HW device ID: 0
warning: argument unused during compilation: '-isystem /cm/shared/apps/graphcore/sdk/3.0.0/lib/graphcore/include'
warning: argument unused during compilation: '-isystem /cm/shared/apps/graphcore/sdk/3.0.0/lib/graphcore/include/c++'
warning: argument unused during compilation: '-isystem /cm/shared/apps/graphcore/sdk/3.0.0/lib/clang/15.0.0/include'
warning: argument unused during compilation: '-isystem /cm/shared/apps/graphcore/sdk/3.0.0/lib/graphcore/include/poplar'
warning: argument unused during compilation: '-isystem /cm/shared/apps/graphcore/sdk/3.0.0/include'
warning: argument unused during compilation: '-I .'
6 warnings generated.
Exception: Unknown vertex type 'VectorAdd (In addVertex for Compute Set cs1).'

I was told in Graphcore Slack that this might be bug. Tried with both Poplar SDK v2.5 and v3.0.

vchuravy commented 1 year ago

Can you try passing CodeletFileType::IrSource directly?

giordano commented 1 year ago

I tried that, and it didn't change much. According to addCodelets docstring the codelet type is inferred from the extension by default (CodeletFileType::Auto)

giordano commented 1 year ago

For the record, I was told that to add a codelet implemented purely in LLVM IR we may have to use addCodeletPlaceholder, to provide extra information which is automatically inferred from the C++ class.

vchuravy commented 1 year ago

Oh neat! That was the function I was looking for. That makes sense to me since I was wondering how the mapping from graph to arguments worked.