Skip to content

[Partitioner] Partitioner refactoring 3 #3384

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

Closed
wants to merge 1 commit into from
Closed

Conversation

beicy
Copy link
Contributor

@beicy beicy commented Aug 5, 2019

Summary:
In this PR:

  1. Added class ParititionerBase which contains interfaces and common functions used for partitioner. and the class Partitioner is now derived from class ParititionerBase .
  2. In class Partitioner, we have 3 partition approaches:
llvm::Error HeterogeneousPartition(CompilationContext &cctx);
llvm::Error QuantizationProfilingPartition(CompilationContext &cctx);
llvm::Error PartitionFromConfig(PartitionConfig &partitionConfig);

The above 3 method can be called directly by users, or chosen by
llvm::Error Partition(CompilationContext &cctx)

Note: loadBalancedPartitioning is still included in HeterogeneousPartition since it uses the result of current partitioner approach. Will take it from HeterogeneousPartition in next PR and make it as the 4th partition approach.

Documentation:

[Optional Fixes #issue]
#2298
Test Plan:
Ninja test, ./tests/image/run.sh
Please see a detailed explanation of how to fill out the fields in the relevant sections in PULL_REQUEST.md.

@beicy beicy force-pushed the ref2 branch 2 times, most recently from cbe8afa to f59a8a8 Compare August 6, 2019 21:18
using namespace runtime;
/// Given a module, partitions each of the its functions into multiple ones
/// based on memory constraints and minimizes the communication cost.
class PartitionerBase {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's clean up this interface a bit as discussed offline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


/// Decompose each function in a module. \p cctx is used in function
/// optimization. \returns whether there was an error encountered.
virtual llvm::Error Partition(CompilationContext &cctx) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: should be lowercase p to match our coding conventions.

/// among different type of devices. \p cctx is used during optimization of
/// the Function. \returns whether there was an error encountered.
llvm::Error Partition(CompilationContext &cctx);
llvm::Error PartitionFromConfig(PartitionConfig &partitionConfig);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same initial-caps nit, here and a few places below.

Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beicy has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@jfix71 jfix71 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW while you're refactoring, how do you feel about dropping the Ty suffix from the partitioner/runtime types? I think @bertmaher has mentioned this before. E.g. DAGListTy, DeviceIDTy, etc.

/// The representative function used for partition. We choose the function who
/// has the largest memory size.
Function *F_;

/// The partition result.
DAGListTy partitions_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense for this to be moved to PartitionerBase? PartitionerBase::partition() will always return a reference to this DAGListTy, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"PartitionerBase::partition() will always return a reference to this DAGListTy, right?"
-- Yes.
"Would it make sense for this to be moved to PartitionerBase? "
-- After the offline discussion with @rdzhabarov, we would like to make the PartitionerBase "stateless".

Copy link
Contributor

@rdzhabarov rdzhabarov Aug 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: do we really need to keep DAGListTy partitions_; in partitioner.

Role of the partitioner is to generate DAGList and return it back to the caller (once generated it's never accessed in partitioner).
What do we gain by keeping partitions_ here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed DAGListTy partitions_; in partitioner.

virtual ~PartitionerBase() = default;

/// Decompose each function in a module. \p cctx is used in function
/// optimization. \returns whether there was an error encountered.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Think this was copy+paste -- but I don't think it's correct anymore to say it returns whether there was an error encountered. In normal circumstances it actually returns the DAGList.

@beicy
Copy link
Contributor Author

beicy commented Aug 7, 2019

BTW while you're refactoring, how do you feel about dropping the Ty suffix from the partitioner/runtime types? I think @bertmaher has mentioned this before. E.g. DAGListTy, DeviceIDTy, etc.

For "Ty", if we decide to move that, I think it is better to get a separate PR, since other parts of Runtime (e.g. Provisioner) use those date type as well.

/// need to be created, we use \p backendsHolder to hold them for memory
/// purpose.
void getBackendMap(std::map<std::string, BackendInfo> &backendMap,
/// Greate the map between the backend name and the concrete backend info
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: Greate -> Create

@beicy beicy force-pushed the ref2 branch 2 times, most recently from 0c52c95 to 8c56fbc Compare August 7, 2019 20:41
Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beicy has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@beicy beicy force-pushed the ref2 branch 2 times, most recently from 64b05ce to c69a38b Compare August 7, 2019 21:31

FunctionToBackendNameMap
backendBasedPartition(Function *F, std::vector<Backend *> &backends,
/// Do the partition based on backend types.
Copy link
Contributor

@rdzhabarov rdzhabarov Aug 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add some description to the doxygen, e.g., what F is and what's stored in functobackend map etc.

/// the Function. \returns whether there was an error encountered.
llvm::Error Partition(CompilationContext &cctx);
llvm::Expected<DAGListTy>
partitionFromConfig(PartitionConfig &partitionConfig);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why config is not a const here?

Function *F,
std::vector<Backend *> backends);
llvm::Expected<DAGListTy>
quantizationProfilingPartition(CompilationContext &cctx);
Copy link
Contributor

@rdzhabarov rdzhabarov Aug 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why all these special methods are part of the public interface of partitioner?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed with @artemrakhov before. It allows users to call those method directly. For example, user-defined partitioner can be called directly without setting params, e.g "optimized_" and "saturateHost_". @artemrakhov could you please also help to double check the interface? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is the right direction! It is very useful to be able to call just one method.

But Roman wanted to bring a different question to your attention. Can we create more Partitioner-based (inherited) classes? I.e. we could further introduce UserDefinedPartitioner, SaturatingPartitioner, and so on. Whatever makes sense. That way, Partitioner class itself won't implement any "special" partitions. It will be a very general class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is the right direction! It is very useful to be able to call just one method.

But Roman wanted to bring a different question to your attention. Can we create more Partitioner-based (inherited) classes? I.e. we could further introduce UserDefinedPartitioner, SaturatingPartitioner, and so on. Whatever makes sense. That way, Partitioner class itself won't implement any "special" partitions. It will be a very general class.

We now have "class PartitionerBase" and new partitioner class can be derived from that. The reason we have current partition flows in Partitioner because they shares lots of common data types, internal members. We would like to keep "class PartitionerBase" stateless.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do further inheritance. For example: PartitionerBase -> Partitioner -> UserDefinedPartitioner

@@ -723,30 +542,20 @@ llvm::Error Partitioner::QuantizationProfilingPartition(
<< "Profiling a model to be partitioned cross different backends. Each "
"sub-network will be optimized and run on cpu backend.\n";
}
return llvm::Error::success();
return partitions;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while refactoring can you replace asserts with DCHECK and add more detail to error message where applicable.

@beicy beicy force-pushed the ref2 branch 4 times, most recently from ecebbe7 to 3f969aa Compare August 8, 2019 04:19
Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beicy has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@beicy beicy force-pushed the ref2 branch 4 times, most recently from 49de964 to b0842f1 Compare August 9, 2019 17:14
Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beicy has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@jfix71 jfix71 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just a series of doxygen/comment stuff.

@@ -83,10 +83,13 @@ class Partitioner {
llvm::StringRef backendName);

/// Duplicates all networks in the module order to saturate the Host.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Update doxygen to mention the method parameters.

/// Partition a function \p F based on backends \p backends. \returns the
/// final result and a map between partitions and backend names.
llvm::Expected<DAGListTy>
backendBasedPartition(FunctionToBackendNameMap &FuncToBackend, Function *F,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: uncapitalize FuncToBackend (matches the cpp definition)

FunctionToBackendNameMap
backendBasedPartition(Function *F, std::vector<Backend *> &backends,
/// Partition a function \p F based on backends \p backends. \returns the
/// final result and a map between partitions and backend names.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Update doxygen with all method params

/// partition result.
void doPartitioning(llvm::StringRef funcName, std::vector<Function *>,
NodeToFunctionMap &mapping, bool saveDAG);

/// If there is no need to do any partition, just generate the DAGNode based
/// on current functions in this module for backend \p backendName found in \p
/// backendMap. \p cctx is used during optimization of the Function. \returns
/// whether there was an error encountered.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This doesn't return if an error was encountered, it returns the DAG list or else an error.

/// the Function. \returns whether there was an error encountered.
llvm::Error Partition(CompilationContext &cctx);
llvm::Expected<DAGListTy>
partitionFromConfig(const PartitionConfig &partitionConfig);

/// This partition approach is used in Glow Quantization Profiling flow. The
/// backendBasedPartition is applied first in case there are heterogeneous
/// backends. Then each sub-function will be compiled and run in CPU backend
/// for profiling.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: \returns ... and mention cctx.

void dumpDAG(llvm::StringRef dotFilename, const DAGListTy &partitions) const;

protected:
/// Given the node-function mapping, do the actual partitioning. If \p saveDAG
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: \p mapping etc. and \returns instead of partitions_.

@@ -237,13 +178,14 @@ NodeToFunctionMap Partitioner::selectPartitions(Function *F,
/// Duplicate the network to saturate the number of devices. For example: If a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this doxygen can be moved to the header?

@@ -825,7 +641,7 @@ llvm::Error Partitioner::Partition(CompilationContext &cctx) {
}

// Step 5 : do the real partitioning for the function list.
doPartitioning(origName, funcs, mapping, true);
partitions = doPartitioning(origName, funcs, module_, mapping, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: /* saveDAG */ true

@@ -931,15 +751,15 @@ llvm::Error Partitioner::PartitionFromConfig() {
// TODO : loop-free validation.

// Do partition.
doPartitioning(F->getName(), {F}, partitionMap, true);
partitions = doPartitioning(F->getName(), {F}, module_, partitionMap, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: /* saveDAG */ true

using namespace glow;
using llvm::isa;

/// Current only partition the representative function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Don't need doxygen in cpp files.

Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beicy has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link

@beicy merged this pull request in 3706588.

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

Successfully merging this pull request may close these issues.

6 participants