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

Feature/try to remove parallel nn #1198

Closed

Conversation

reyoung
Copy link
Collaborator

@reyoung reyoung commented Jan 19, 2017

Try to remove parallel_nn by using protobuf.
Done.

Related issue #852

@reyoung reyoung force-pushed the feature/try_to_remove_parallel_nn branch from 6599dd6 to 38bd032 Compare January 19, 2017 14:46
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
syntax = "proto2";
Copy link
Contributor

@gangliao gangliao Jan 19, 2017

Choose a reason for hiding this comment

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

所以还是用proto2的语法?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

这里主要是还要被其他的protobuf引用,所以还得用proto2的吧。

如果把Paddle内部的proto2语法都升级到3,是一个特别大的工程。(主要是proto3没有default value)了。

@wangkuiyi
Copy link
Collaborator

我搜了一下 parallel_nn 的用法:

for i in $(du -a | grep '\.h$' | cut -f 2); do if grep parallel_nn $i; then echo ==== $i ====; fi; done
for i in $(du -a | grep '\.cpp$' | cut -f 2); do if grep parallel_nn $i; then echo ==== $i ====; fi; done

看上去是在gradient machine、network、和layer里面用的。

那么是不是应该是这几个相关的class里要增加一个data member呢?

另外,我没有领会 parallel_nn 是什么意思?并行的neural network?是说网络拓扑上有两个nn是并行的(平行线)?还是说计算的时候有两个线程是并行的?

@reyoung
Copy link
Collaborator Author

reyoung commented Jan 21, 2017

另外,我没有领会 parallel_nn 是什么意思?并行的neural network?是说网络拓扑上有两个nn是并行的(平行线)?还是说计算的时候有两个线程是并行的?

Parallel NeuralNetwork在Paddle里面指的是单机模型并行的开关,即可以设置不同的Layer和参数在不同的设备上(显卡1,显卡2,CPU)。

那么是不是应该是这几个相关的class里要增加一个data member呢?

其实我做了一个类似的事情,就是在Layer,network的protobuf配置里面,增加了一个CMDArgument的字段。也就是这个DataMember是放在Protobuf里面了。好处是

  1. protobuf用其他语言传进来比较方便。
  2. 解析Paddle的所有protobuf配置,都在Trainer模块里面进行,天然的就在Main函数里面。
  3. 在原来的protobuf里面增加字段,就不需要修改这些类的构造函数了,因为原来的配置也是通过protobuf传进来的。


namespace paddle {

static ClassRegistrar<ActivationFunction> gActivationRegistrar;
static ClassRegistrar<ActivationFunction, const CMDArguments&>
Copy link
Collaborator

Choose a reason for hiding this comment

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

CMD不是synonym,不应该全大写。

另外,“命令行参数”是command-line arguments, 不是command arguments。


namespace paddle {

template <typename T>
Copy link
Collaborator

@wangkuiyi wangkuiyi Jan 21, 2017

Choose a reason for hiding this comment

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

这template有“炫技”的嫌疑?:-D 把配置信息传进来应该不需要template吧。

Copy link
Collaborator

@wangkuiyi wangkuiyi left a comment

Choose a reason for hiding this comment

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

虽然我还没有看明白源码,但是我对增加一个protobuf message的方法很有疑虑。

在想明白之前,再问一个问题:

Parallel NeuralNetwork在Paddle里面指的是单机模型并行的开关,即可以设置不同的Layer和参数在不同的设备上(显卡1,显卡2,CPU)。

如果 parallel_nn == true,那么每个layer到底在哪个GPU上执行,是怎么决定的?

我看貌似是 act.deviceId 决定的。那么就用永远假设 parallel_nn 为 true,从而去掉这个flag可以吗?

syntax = "proto2";
package paddle;

message CMDArguments {
Copy link
Collaborator

Choose a reason for hiding this comment

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

我们清理全局变量,本来是想把代码变得更简单。这个办法竟然需要增加一个protobuf定义,还要在各个activation function classes里增加一个class member。反而把代码变复杂了。

@reyoung
Copy link
Collaborator Author

reyoung commented Jan 21, 2017

如果 parallel_nn == true,那么每个layer到底在哪个GPU上执行,是怎么决定的?

在配置网络的时候,会对每一个Layer传递一个device值。-1表示CPU,0表示GPU0(第一块GPU卡)。这个Layer的device值,会影响这个Layer里面参数的device和Activation的device。

在parallel_nn=True的时候,每一层的运算设备会和这个device值一致。

当Parallel_nn=False的时候,整体网络都在一个设备里面执行。具体在哪个设备里面执行,由 use_gpu=True/False, trainer_count, gpu_id这几个命令行参数共同决定。

@reyoung
Copy link
Collaborator Author

reyoung commented Jan 22, 2017

我们清理全局变量,本来是想把代码变得更简单。这个办法竟然需要增加一个protobuf定义,还要在各个activation function classes里增加一个class member。反而把代码变复杂了。

我在想,我们需要去掉的全局变量可能是几十个,如果我们没有『一个』简单的手法的话,可能会变得比较复杂。

而对于去掉命令行参数的全局变量,传递命令行参数到Paddle内部来说,似乎使用protobuf比较简单。因为,Paddle几乎每一个复杂的类,都会有一个Protobuf的config字段(LayerConfig, ModelConfig, etc)。

我担心,我们如果为每一个命令行参数『量身定制』如何去掉全局变量,这会让我的任务 #852 没办法拆分给多人做。

所以,我觉得不使用protobuf也是可以的。但是还是要尽量的能够有一个简单容易理解的方法去掉parallel_nn。让所有的flags都可以按照这个PR的方法来完成。这样我们剩下的工作才更容易开展。

@wangkuiyi
Copy link
Collaborator

wangkuiyi commented Jan 23, 2017

感谢清晰描述 parallel_nn 的用途和用法。我理解我们不能简单的忽略parallel_nn了。

我赞同我们要有一个有效的,可重复的手段,来解决全局变量的问题。我自己的办法是利用 woboq codebrowser。

使用 woboq

以下是我今天使用 woboq 和 grep 的实践过程:

首先,在我用woboq生成的一份可浏览的paddle源码里,我们可以把鼠标挪到 FLAGS_parallel_nn 的定义上,然后在浮动窗口里看到它都在哪些地方被使用了(一共30处):

screen shot 2017-01-22 at 6 12 02 pm

这个工作也可以用bash和grep来做:

$ for i in $(du -a | grep '\.\(cpp\|h\)$' | cut -f 2); do if grep FLAGS_parallel_nn $i > /dev/null; then echo $i; fi; done
./gserver/gradientmachines/GradientMachine.cpp
./gserver/gradientmachines/MultiGradientMachine.cpp
./gserver/gradientmachines/MultiNetwork.cpp
./gserver/gradientmachines/NeuralNetwork.cpp
./gserver/layers/Layer.cpp
./parameter/Parameter.cpp
./trainer/tests/test_CompareSparse.cpp
./trainer/tests/test_Trainer.cpp
./trainer/tests/test_TrainerOnePass.cpp
./trainer/Trainer.cpp
./trainer/TrainerConfigHelper.cpp
./utils/Util.h

从解决 trainer/Trainer.cpp 里的用法开始

首先我们看看上面列表里的 trainer/Trainer.cpp 里的FLAGS_parallel_nn的用法:

  1. 这文件里只有一处用到 FLAGS_parallel_nn。这一处在 Trainer::init 的定义里。

  2. woboq 展示出Trainer::init 一共在多处被调用。其中一处是 main @ TrainerMain.cpp

所以,我们需要做的修改是:

  1. main函数里parse commandline flag parallel_nn,

  2. 然后给 Trainer::init 增加一个参数 parallel_nn,并且从main把parallel_nn传递给 Trainer::init

另一个例子

类似的工作方法也适用于 ./gserver/gradientmachines/GradientMachine.cpp

  1. FLAGS_parallel_nn的用处在 GradientMachine::create里,

  2. 它被 TrainerInternal::init 调用。

  3. TrainerInternal::init 是被 Trainer::init 调用的。在上面提议的修改里,我们已经让 main 把 parallel_nn 传递给 Trainer::init了,所以可以继续通过 TrainerInternal::init 传递给 GradientMachine。

Layers 里的用法

我猜上述两个例子里的用法也适用于解决 MultiGradientMachine 里的 FLAGS_parallel_nn 的用法。

我也注意到 Layers.cpp 里的解决方法会有所不同,因为 Layer.init 是被一个 macro 调用的。所以这个PR修改那个 macro 来传入一个 CMDArgument protobuf message。

我目前的理解是:

  1. 这里不需要一个protobuf message,只需要增加一个C++ class。
  2. 这个C++ class貌似应该叫做 Model,而不是CMDArgument。
  3. 每个Layer貌似应该有一个data member:const Model* model_ 指向这个class的一个实例。

@reyoung
Copy link
Collaborator Author

reyoung commented Jan 23, 2017

closed due to I will give a better way to remove the parallel nn flag

@reyoung reyoung closed this Jan 23, 2017
zhhsplendid pushed a commit to zhhsplendid/Paddle that referenced this pull request Sep 25, 2019
* refine the equal api doc test=develop

* refine doc test=develop

* fix according the standard doc test=develop

* fix the doc test=develop

* review fix test=develop

* fix review test=develop

* fix review test=develop

* fix from standard test=develop

* add fix test=develop
wangxicoding pushed a commit to wangxicoding/Paddle that referenced this pull request Dec 9, 2021
* fix seq2seq windows dtype bug

* fix

Co-authored-by: Zeyu Chen <chenzeyu01@baidu.com>
lizexu123 pushed a commit to lizexu123/Paddle that referenced this pull request Feb 23, 2024
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

Successfully merging this pull request may close these issues.

3 participants