Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into fluid_benchmark_support_recordioreader
commit
a28a462e19
@ -0,0 +1,127 @@
|
|||||||
|
# How to use RecordIO in Fluid
|
||||||
|
|
||||||
|
If you want to use RecordIO as your training data format, you need to convert to your training data
|
||||||
|
to RecordIO files and reading them in the process of training, PaddlePaddle Fluid provides some
|
||||||
|
interface to deal with the RecordIO files.
|
||||||
|
|
||||||
|
## Generate RecordIO File
|
||||||
|
|
||||||
|
Before start training with RecordIO files, you need to convert your training data
|
||||||
|
to RecordIO format by `fluid.recordio_writer.convert_reader_to_recordio_file`, the sample codes
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
```python
|
||||||
|
reader = paddle.batch(mnist.train(), batch_size=1)
|
||||||
|
feeder = fluid.DataFeeder(
|
||||||
|
feed_list=[ # order is image and label
|
||||||
|
fluid.layers.data(
|
||||||
|
name='image', shape=[784]),
|
||||||
|
fluid.layers.data(
|
||||||
|
name='label', shape=[1], dtype='int64'),
|
||||||
|
],
|
||||||
|
place=fluid.CPUPlace())
|
||||||
|
fluid.recordio_writer.convert_reader_to_recordio_file('./mnist.recordio', reader, feeder)
|
||||||
|
```
|
||||||
|
|
||||||
|
The above code snippet would generate a RecordIO `./mnist.recordio` on your host.
|
||||||
|
|
||||||
|
**NOTE**: we recommend users to set `batch_size=1` when generating the recordio files so that users can
|
||||||
|
adjust it flexibly while reading it.
|
||||||
|
|
||||||
|
## Use the RecordIO file in a Local Training Job
|
||||||
|
|
||||||
|
PaddlePaddle Fluid provides an interface `fluid.layers.io.open_recordio_file` to load your RecordIO file
|
||||||
|
and then you can use them as a Layer in your network configuration, the sample codes as follows:
|
||||||
|
|
||||||
|
```python
|
||||||
|
data_file = fluid.layers.io.open_recordio_file(
|
||||||
|
filename="./mnist.recordio",
|
||||||
|
shapes=[(-1, 784),(-1, 1)],
|
||||||
|
lod_levels=[0, 0],
|
||||||
|
dtypes=["float32", "int32"])
|
||||||
|
data_file = fluid.layers.io.batch(data_file, batch_size=4)
|
||||||
|
|
||||||
|
img, label = fluid.layers.io.read_file(data_file)
|
||||||
|
hidden = fluid.layers.fc(input=img, size=100, act='tanh')
|
||||||
|
prediction = fluid.layers.fc(input=hidden, size=10, act='softmax')
|
||||||
|
loss = fluid.layers.cross_entropy(input=prediction, label=label)
|
||||||
|
avg_loss = fluid.layers.mean(loss)
|
||||||
|
|
||||||
|
fluid.optimizer.Adam(learning_rate=1e-3).minimize(avg_loss)
|
||||||
|
|
||||||
|
place = fluid.CPUPlace()
|
||||||
|
|
||||||
|
exe = fluid.Executor(place)
|
||||||
|
exe.run(fluid.default_startup_program())
|
||||||
|
avg_loss_np = []
|
||||||
|
|
||||||
|
# train a pass
|
||||||
|
batch_id = 0
|
||||||
|
while True:
|
||||||
|
tmp, = exe.run(fetch_list=[avg_loss])
|
||||||
|
|
||||||
|
avg_loss_np.append(tmp)
|
||||||
|
print(batch_id)
|
||||||
|
batch_id += 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the RecordIO files in Distributed Training
|
||||||
|
|
||||||
|
1. generate multiple RecordIO files
|
||||||
|
|
||||||
|
For a distributed training job, you may have multiple trainer nodes,
|
||||||
|
and one or more RecordIO files for one trainer node, you can use the interface
|
||||||
|
`fluid.recordio_writer.convert_reader_to_recordio_files` to convert your training data
|
||||||
|
into multiple RecordIO files, the sample codes as follows:
|
||||||
|
|
||||||
|
```python
|
||||||
|
reader = paddle.batch(mnist.train(), batch_size=1)
|
||||||
|
feeder = fluid.DataFeeder(
|
||||||
|
feed_list=[ # order is image and label
|
||||||
|
fluid.layers.data(
|
||||||
|
name='image', shape=[784]),
|
||||||
|
fluid.layers.data(
|
||||||
|
name='label', shape=[1], dtype='int64'),
|
||||||
|
],
|
||||||
|
place=fluid.CPUPlace())
|
||||||
|
fluid.recordio_writer.convert_reader_to_recordio_files(
|
||||||
|
filename_suffix='./mnist.recordio', batch_per_file=100, reader, feeder)
|
||||||
|
```
|
||||||
|
|
||||||
|
The above codes would generate multiple RecordIO files on your host like:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.
|
||||||
|
\_mnist-00000.recordio
|
||||||
|
|-mnist-00001.recordio
|
||||||
|
|-mnist-00002.recordio
|
||||||
|
|-mnist-00003.recordio
|
||||||
|
|-mnist-00004.recordio
|
||||||
|
```
|
||||||
|
|
||||||
|
2. open multiple RecordIO files by `fluid.layers.io.open_files`
|
||||||
|
|
||||||
|
For a distributed training job, the distributed operator system will schedule trainer process on multiple nodes,
|
||||||
|
each trainer process reads parts of the whole training data, we usually take the following approach to make the training
|
||||||
|
data allocated by each trainer process as uniform as possiable:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def gen_train_list(file_pattern, trainers, trainer_id):
|
||||||
|
file_list = glob.glob(file_pattern)
|
||||||
|
ret_list = []
|
||||||
|
for idx, f in enumerate(file_list):
|
||||||
|
if (idx + trainers) % trainers == trainer_id:
|
||||||
|
ret_list.append(f)
|
||||||
|
return ret_list
|
||||||
|
|
||||||
|
trainers = int(os.getenv("TRAINERS"))
|
||||||
|
trainer_id = int(os.getenv("PADDLE_INIT_TRAINER_ID"))
|
||||||
|
data_file = fluid.layers.io.open_files(
|
||||||
|
filenames=gen_train_list("./mnist-[0-9]*.recordio", 2, 0),
|
||||||
|
thread_num=1,
|
||||||
|
shapes=[(-1, 784),(-1, 1)],
|
||||||
|
lod_levels=[0, 0],
|
||||||
|
dtypes=["float32", "int32"])
|
||||||
|
img, label = fluid.layers.io.read_file(data_files)
|
||||||
|
...
|
||||||
|
```
|
@ -1 +0,0 @@
|
|||||||
../../../../../benchmark/cluster/README.md
|
|
@ -1 +0,0 @@
|
|||||||
../../../../../../benchmark/cluster/vgg16/README.md
|
|
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
inference_api_test(simple_on_word2vec ARGS test_word2vec)
|
@ -0,0 +1,71 @@
|
|||||||
|
/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains a simple demo for how to take a model for inference.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <memory>
|
||||||
|
#include "paddle/contrib/inference/paddle_inference_api.h"
|
||||||
|
|
||||||
|
namespace paddle {
|
||||||
|
namespace demo {
|
||||||
|
|
||||||
|
DEFINE_string(dirname, "", "Directory of the inference model.");
|
||||||
|
|
||||||
|
void Main(bool use_gpu) {
|
||||||
|
//# 1. Create PaddlePredictor with a config.
|
||||||
|
NativeConfig config;
|
||||||
|
config.model_dir = FLAGS_dirname + "word2vec.inference.model";
|
||||||
|
config.use_gpu = use_gpu;
|
||||||
|
config.fraction_of_gpu_memory = 0.15;
|
||||||
|
config.device = 0;
|
||||||
|
auto predictor =
|
||||||
|
CreatePaddlePredictor<NativeConfig, PaddleEngineKind::kNative>(config);
|
||||||
|
|
||||||
|
for (int batch_id = 0; batch_id < 3; batch_id++) {
|
||||||
|
//# 2. Prepare input.
|
||||||
|
int64_t data[4] = {1, 2, 3, 4};
|
||||||
|
|
||||||
|
PaddleBuf buf{.data = data, .length = sizeof(data)};
|
||||||
|
PaddleTensor tensor{.name = "",
|
||||||
|
.shape = std::vector<int>({4, 1}),
|
||||||
|
.data = buf,
|
||||||
|
.dtype = PaddleDType::INT64};
|
||||||
|
|
||||||
|
// For simplicity, we set all the slots with the same data.
|
||||||
|
std::vector<PaddleTensor> slots(4, tensor);
|
||||||
|
|
||||||
|
//# 3. Run
|
||||||
|
std::vector<PaddleTensor> outputs;
|
||||||
|
CHECK(predictor->Run(slots, &outputs));
|
||||||
|
|
||||||
|
//# 4. Get output.
|
||||||
|
ASSERT_EQ(outputs.size(), 1UL);
|
||||||
|
LOG(INFO) << "output buffer size: " << outputs.front().data.length;
|
||||||
|
const size_t num_elements = outputs.front().data.length / sizeof(float);
|
||||||
|
// The outputs' buffers are in CPU memory.
|
||||||
|
for (size_t i = 0; i < std::min(5UL, num_elements); i++) {
|
||||||
|
LOG(INFO) << static_cast<float*>(outputs.front().data.data)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(demo, word2vec_cpu) { Main(false /*use_gpu*/); }
|
||||||
|
TEST(demo, word2vec_gpu) { Main(true /*use_gpu*/); }
|
||||||
|
|
||||||
|
} // namespace demo
|
||||||
|
} // namespace paddle
|
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <cuda.h>
|
||||||
|
|
||||||
|
#include "paddle/contrib/inference/paddle_inference_api_anakin_engine.h"
|
||||||
|
|
||||||
|
namespace paddle {
|
||||||
|
|
||||||
|
PaddleInferenceAnakinPredictor::PaddleInferenceAnakinPredictor(
|
||||||
|
const AnakinConfig &config) {
|
||||||
|
CHECK(Init(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PaddleInferenceAnakinPredictor::Init(const AnakinConfig &config) {
|
||||||
|
// TODO(Superjomn) Tell anakin to support return code.
|
||||||
|
engine_.Build(config.model_file, config.max_batch_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PaddleInferenceAnakinPredictor::Run(
|
||||||
|
const std::vector<PaddleTensor> &inputs,
|
||||||
|
std::vector<PaddleTensor> *output_data) {
|
||||||
|
for (const auto &input : inputs) {
|
||||||
|
if (input.dtype != PaddleDType::FLOAT32) {
|
||||||
|
LOG(ERROR) << "Only support float type inputs. " << input.name
|
||||||
|
<< "'s type is not float";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
engine_.SetInputFromCPU(
|
||||||
|
input.name, static_cast<float *>(input.data.data), input.data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Superjomn) Tell anakin to support return code.
|
||||||
|
engine_.Execute();
|
||||||
|
|
||||||
|
if (output_data->empty()) {
|
||||||
|
LOG(ERROR) << "At least one output should be set with tensors' names.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto &output : *output_data) {
|
||||||
|
auto *tensor = engine_.GetOutputInGPU(output.name);
|
||||||
|
output.shape = tensor->shape();
|
||||||
|
// Copy data from GPU -> CPU
|
||||||
|
if (cudaMemcpy(output.data.data,
|
||||||
|
tensor->data(),
|
||||||
|
tensor->size(),
|
||||||
|
cudaMemcpyDeviceToHost) != 0) {
|
||||||
|
LOG(ERROR) << "copy data from GPU to CPU error";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Superjomn) To implement latter.
|
||||||
|
std::unique_ptr<PaddlePredictor> PaddleInferenceAnakinPredictor::Clone() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A factory to help create difference predictor.
|
||||||
|
template <>
|
||||||
|
std::unique_ptr<PaddlePredictor>
|
||||||
|
CreatePaddlePredictor<AnakinConfig, PaddleEngineKind::kAnakin>(
|
||||||
|
const AnakinConfig &config) {
|
||||||
|
std::unique_ptr<PaddlePredictor> x(
|
||||||
|
new PaddleInferenceAnakinPredictor(config));
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace paddle
|
@ -0,0 +1,51 @@
|
|||||||
|
/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains the implementation of inference API with Anakin engine
|
||||||
|
* embeded, this API can only support Anakin models.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// NOTE This header file do not have namespace.
|
||||||
|
// TODO(Superjomn) Tell Anakin to provide better APIs.
|
||||||
|
#include <test/framework/net/paddle_api.h>
|
||||||
|
#include "paddle/contrib/inference/paddle_inference_api.h"
|
||||||
|
|
||||||
|
namespace paddle {
|
||||||
|
|
||||||
|
class PaddleInferenceAnakinPredictor : public PaddlePredictor {
|
||||||
|
public:
|
||||||
|
PaddleInferenceAnakinPredictor(const AnakinConfig& config);
|
||||||
|
|
||||||
|
// NOTE Unlike the native engine, the buffers of anakin engine's output_data
|
||||||
|
// should be allocated first.
|
||||||
|
// TODO(Superjomn) should unify all the behaviors of output_data accross all
|
||||||
|
// the engines.
|
||||||
|
bool Run(const std::vector<PaddleTensor>& inputs,
|
||||||
|
std::vector<PaddleTensor>* output_data) override;
|
||||||
|
|
||||||
|
std::unique_ptr<PaddlePredictor> Clone() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Init(const AnakinConfig& config);
|
||||||
|
|
||||||
|
anakin::AnakinEngine<anakin::NV,
|
||||||
|
anakin::saber::AK_FLOAT,
|
||||||
|
anakin::Precision::FP32>
|
||||||
|
engine_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace paddle
|
@ -0,0 +1,27 @@
|
|||||||
|
/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#include "paddle/contrib/inference/paddle_inference_api.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace paddle {
|
||||||
|
|
||||||
|
TEST(inference, anakin) {
|
||||||
|
AnakinConfig config;
|
||||||
|
|
||||||
|
auto engine =
|
||||||
|
CreatePaddlePredictor<AnakinConfig, PaddleEngineKind::kAnakin>(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace paddle
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue