**Use case**

Generate models once and reuse them.

**Describe the solution you'd like**

Add command line options:
```
--save file - write serialized models on disk after training and before generating the data; the user can set --limit to 0 to only train the models and save them without proceeding to data generation;
--load file - instead of training the models, load the prepared models from the file and start generating the data.
```

Serialization format: one byte for version (equals to 0), then simple binary serialization of all the models; the whole file is compressed with ZSTD level 1 using CompressedWriteBuffer (no need to allow any compression options to choose).
{
        if (!silent)
            std::cerr << "Training models\n";
        Pipe pipe(context->getInputFormat(input_format, file_in, header, max_block_size));
        QueryPipeline pipeline(std::move(pipe));
        PullingPipelineExecutor executor(pipeline);
        Block block;
        while (executor.pull(block))
        {
            obfuscator.train(block.getColumns());
            source_rows += block.rows();
            if (!silent)
                std::cerr << "Processed " << source_rows << " rows\n";
        }
    }
    obfuscator.finalize();
    if (!limit)
        limit = source_rows;
    
    UInt64 processed_rows = 0;
    while (processed_rows < limit)
    {
        if (!silent)
            std::cerr << "Generating data\n";
        file_in.seek(0, SEEK_SET);
        Pipe pipe(context->getInputFormat(input_format, file_in, header, max_block_size));
        if (processed_rows + source_rows > limit)
        {
            pipe.addSimpleTransform([&](const Block & cur_header)
            {