Skip to content

Commit

Permalink
[feat] add pipeline.trim function.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChunelFeng committed Sep 1, 2024
1 parent 3351726 commit 3a6d690
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 31 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ int main() {
[2024.07.27 - v2.6.1 - Chunel]
* 提供`pipeline`的静态执行的方式,提供微任务机制
* 优化`event`(事件)机制,异步事件可以等待结束
* 提供`pipeline`剪裁功能,用于删除`element`之间重复的依赖

</details>

Expand Down
14 changes: 14 additions & 0 deletions src/GraphCtrl/GraphElement/GElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,4 +566,18 @@ CBool GElement::isDefaultBinding() const {
return CGRAPH_DEFAULT_BINDING_INDEX == binding_index_;
}


CBool GElement::removeDepend(GElementPtr element) {
CGRAPH_ASSERT_NOT_NULL_THROW_ERROR(element)
CGRAPH_ASSERT_INIT_THROW_ERROR(false)
if (!dependence_.hasValue(element)) {
return false;
}

dependence_.remove(element);
element->run_before_.remove(this);
left_depend_.store(dependence_.size(), std::memory_order_release);
return true;
}

CGRAPH_NAMESPACE_END
10 changes: 9 additions & 1 deletion src/GraphCtrl/GraphElement/GElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,13 @@ class GElement : public GElementObject,
*/
CBool isDefaultBinding() const;

/**
* 删除一个依赖的节点信息
* @param element
* @return
*/
CBool removeDepend(GElement* element);

private:
/** 状态相关信息 */
CBool done_ { false }; // 判定被执行结束
Expand All @@ -444,7 +451,7 @@ class GElement : public GElementObject,
CBool is_prepared_ { false }; // 判断是否已经执行过 prepareRun() 方法

/** 图相关信息 */
std::atomic<CSize> left_depend_ { 0 }; // 当 left_depend_ 值为0的时候,即可以执行该element信息
std::atomic<CSize> left_depend_ { 0 }; // 当 left_depend_ 值为0的时候,即可以执行该element信息
USmallVector<GElement *> run_before_; // 被依赖的节点(后继)
USmallVector<GElement *> dependence_; // 依赖的节点信息(前驱)
GElement* belong_ { nullptr }; // 从属的element 信息,如为nullptr,则表示从属于 pipeline
Expand Down Expand Up @@ -477,6 +484,7 @@ class GElement : public GElementObject,
friend class GAspectObject;
friend class GOptimizer;
friend class GMaxParaOptimizer;
friend class GTrimOptimizer;
friend class GSeparateOptimizer;
friend class GElementRepository;
friend class GPerf;
Expand Down
5 changes: 5 additions & 0 deletions src/GraphCtrl/GraphElement/GElementManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ CBool GElementManager::checkSerializable() {
}


CSize GElementManager::trim() {
return GTrimOptimizer::trim(manager_elements_);
}


CStatus GElementManager::process(const GSortedGElementPtrSet& elements) {
CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_NOT_NULL(engine_)
Expand Down
6 changes: 6 additions & 0 deletions src/GraphCtrl/GraphElement/GElementManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ class GElementManager : public GElementObject,
*/
CBool checkSerializable();

/**
* 剪裁多余的连边信息
* @return
*/
CSize trim();

/**
* 加入数据,并且执行
* @param elements
Expand Down
33 changes: 3 additions & 30 deletions src/GraphCtrl/GraphElement/_GOptimizer/GMaxParaOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,12 @@ class GMaxParaOptimizer : public GOptimizer {
* 2. 根据路径,生成一张全连通图,然后将图取反,得到对应的补图(reGraph)
* 3. 计算补图的最大团中元素个数(maxCliqueSize),即为当前dag的最大并行度
*/
const CSize size = elements.size();
const auto& paths = GOptimizer::collectPaths(elements); // 根据传入的elements 的关系,分析出所有完整路径信息

std::vector<std::vector<int>> reGraph(size, std::vector<int>(size, 1));
buildReverseGraph(elements, paths, reGraph); // 根据路径信息,求出全连接图的补图

CSize maxCliqueSize = calcMaxCliqueSize(reGraph); // 计算最大团信息
const auto& paths = collectPaths(elements);
const auto& reGraph = buildGraph(elements, paths, 0, 0, 1);
CSize maxCliqueSize = calcMaxCliqueSize(reGraph);
return maxCliqueSize;
}

/**
* 基于原有dag,计算出所有链路的全连接的补图,记作graph
* @param elements
* @param paths
* @param graph
* @return
*/
static CVoid buildReverseGraph(const GSortedGElementPtrSet& elements,
const std::vector<std::vector<GElementPtr>>& paths,
std::vector<std::vector<int>>& graph) {
for (auto& path : paths) {
for (int i = 0; i < path.size() - 1; i++) {
// 这里的 find是一定能找到的。因为path的数据,是从elements中记录的
int height = (int)std::distance(elements.begin(), elements.find(path[i]));
for (int j = i + 1; j < path.size(); j++) {
int column = (int)std::distance(elements.begin(), elements.find(path[j]));
graph[height][column] = 0;
graph[column][height] = 0; // 因为需要记录的是补图,所以将默认值设置为1,符合条件的设置为0
}
}
}
}

/**
* 计算当前最大团的大小
* @param graph
Expand Down
30 changes: 30 additions & 0 deletions src/GraphCtrl/GraphElement/_GOptimizer/GOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef CGRAPH_GOPTIMIZER_H
#define CGRAPH_GOPTIMIZER_H

#include <vector>

#include "../GElementObject.h"

CGRAPH_NAMESPACE_BEGIN
Expand Down Expand Up @@ -54,6 +56,34 @@ class GOptimizer : public GElementObject {
return paths;
}

/**
* 构造对应的二维矩阵图
* @param elements
* @param paths
* @param father
* @param son
* @param unlink
* @return
*/
static std::vector<std::vector<int>> buildGraph(const GSortedGElementPtrSet& elements,
const std::vector<std::vector<GElementPtr>>& paths,
int father, int son, int unlink) {
const CSize size = elements.size();
std::vector<std::vector<int>> graph(size, std::vector<int>(size, unlink));
for (auto& path : paths) {
for (int i = 0; i < path.size() - 1; i++) {
// 这里的 find是一定能找到的。因为path的数据,是从elements中记录的
int height = (int)std::distance(elements.begin(), elements.find(path[i]));
for (int j = i + 1; j < path.size(); j++) {
int column = (int)std::distance(elements.begin(), elements.find(path[j]));
graph[height][column] = father;
graph[column][height] = son;
}
}
}
return graph;
}

friend class GPerf;
};

Expand Down
1 change: 1 addition & 0 deletions src/GraphCtrl/GraphElement/_GOptimizer/GOptimizerInclude.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
#include "GOptimizer.h"
#include "GMaxParaOptimizer.h"
#include "GSeparateOptimizer.h"
#include "GTrimOptimizer.h"

#endif //CGRAPH_GOPTIMIZERINCLUDE_H
59 changes: 59 additions & 0 deletions src/GraphCtrl/GraphElement/_GOptimizer/GTrimOptimizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/***************************
@Author: Chunel
@Contact: [email protected]
@File: GTrimOptimizer.h
@Time: 2024/9/1 13:59
@Desc:
***************************/

#ifndef CGRAPH_GTRIMOPTIMIZER_H
#define CGRAPH_GTRIMOPTIMIZER_H

#include <algorithm>
#include <iterator>

#include "GOptimizer.h"

CGRAPH_NAMESPACE_BEGIN

class GTrimOptimizer : public GOptimizer {
/**
* 针对图结构,做剪裁
* @param elements
* @return
*/
static CSize trim(GSortedGElementPtrSet& elements) {
CSize trimNum = 0;
const auto& paths = collectPaths(elements);
auto graph = buildGraph(elements, paths, 1, 0, 0);

for (auto* cur : elements) {
int idx = (int)std::distance(elements.begin(), elements.find(cur));
GElementPtrArr candidates;
for (int i = 0; i < (int)cur->dependence_.size(); i++) {
int x = (int)std::distance(elements.begin(), elements.find(cur->dependence_[i]));
for (int j = i; j < (int)cur->dependence_.size(); j++) {
int y = (int)std::distance(elements.begin(), elements.find(cur->dependence_[j]));
if (1 == graph[x][y]) {
graph[x][idx] = 0;
candidates.push_back(cur->dependence_[i]);
}
}
}

for (auto* candidate : candidates) {
if (cur->removeDepend(candidate)) {
trimNum++;
}
}
}

return trimNum;
}

friend class GElementManager;
};

CGRAPH_NAMESPACE_END

#endif //CGRAPH_GTRIMOPTIMIZER_H
8 changes: 8 additions & 0 deletions src/GraphCtrl/GraphPipeline/GPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,11 +262,19 @@ GPipelinePtr GPipeline::setAutoCheck(CBool enable) {


CSize GPipeline::getMaxPara() {
CGRAPH_ASSERT_INIT_THROW_ERROR(false)
CGRAPH_ASSERT_NOT_NULL_THROW_ERROR(element_manager_)
return element_manager_->calcMaxParaSize();
}


CSize GPipeline::trim() {
CGRAPH_ASSERT_INIT_THROW_ERROR(false)
CGRAPH_ASSERT_NOT_NULL_THROW_ERROR(element_manager_)
return element_manager_->trim();
}


CStatus GPipeline::makeSerial() {
CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_INIT(false)
Expand Down
6 changes: 6 additions & 0 deletions src/GraphCtrl/GraphPipeline/GPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,12 @@ class GPipeline : public GPipelineObject,
*/
CSize getMaxPara();

/**
* 针对图结构,做多余边剪裁
* @return 返回值表示裁剪了多少条信息
*/
CSize trim();

/**
* 将符合串行执行条件的pipeline,设定为串行执行的模式。可以大幅度提升运行性能。
* @return
Expand Down
18 changes: 18 additions & 0 deletions src/UtilsCtrl/Container/USmallVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ class USmallVector : public UtilsObject {
memset(data_, 0, sizeof(T) * capacity_);
}

CBool remove(const T& val) {
CBool result = false;
for (CSize i = 0; i < cur_index_; i++) {
if (data_[i] == val) {
for (CSize j = i; j < cur_index_ - 1; j++) {
data_[j] = data_[j + 1];
}
cur_index_--;
result = true;
break;
}
}
return result;
}


/**
* 判断内部是否包含该值
* @param val
Expand Down Expand Up @@ -122,6 +138,8 @@ class USmallVector : public UtilsObject {
UIter end() const { return UIter(data_ + cur_index_); }
T front() const { return data_[0]; }
T back() const { return data_[cur_index_ - 1]; }
T& operator[](CSize index) { return data_[index]; }
const T& operator[](CSize index) const { return data_[index]; }

private:
T* data_ { nullptr }; // 存放具体数据
Expand Down

0 comments on commit 3a6d690

Please sign in to comment.