У меня есть проблема, когда я генерирую большие объемы данных, а затем обрабатываю эти данные.
Концептуально, я думал, что создам одну программу для генерации данных, а затем другую для ее обработки, но я беспокоился о времени передачи данных из одной программы в другую.
Таким образом, я решил оценить, какие издержки у меня были бы, если бы я разделил эти два процесса по сравнению с включением генерации и обработки данных в одной программе.
Код ниже довольно длинный, все, что он делает, это генерирует случайные данные, затем сравнивает stdio::pipe
с std::memcpy
с точки зрения копирования случайных данных в другой вектор.
Однако я получаю результаты, которые не имеют смысла, когда конвейер + генерация данных не только быстрее, чем memcpy, но и быстрее, чем генерация данных в одиночку.
Что я неправильно понимаю?
Генерация данных:
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <vector>
#include <cstring>
#include <ctime>
#define BUFFER_SIZE 1000
#define MYDATA_SIZE 100000000 // ~400 MB
std::vector<int> makeData() {
std::srand(std::time(nullptr));
std::vector<int> data(MYDATA_SIZE);
std::generate(data.begin(), data.end(), std::rand);
return data;
}
int main() {
auto data = makeData();
fwrite(data.data(), 4, data.size(), stdout);
return 0;
}
// g++ -std=c++11 -O3 test2.cpp -o test2
Обработка данных:
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <vector>
#include <cstring>
#include <ctime>
#include <numeric>
#include <random>
#define BUFFER_SIZE 1000
#define MYDATA_SIZE 100000000 // ~400 MB
std::vector<int> makeData() {
std::srand(std::time(nullptr));
std::vector<int> data(MYDATA_SIZE);
std::generate(data.begin(), data.end(), std::rand);
return data;
}
std::vector<int> copyDataFromProcess(std::string cmd) {
std::vector<int> buffer(BUFFER_SIZE);
std::vector<int> result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
size_t bytes_read;
while ( (bytes_read = fread(buffer.data(), 4, buffer.size(), pipe.get())) ) {
result.insert(result.end(), buffer.begin(), buffer.begin() + bytes_read);
}
return result;
}
std::vector<int> copyDataFromInternal() {
std::vector<int> mydata = makeData();
std::vector<int> result(MYDATA_SIZE);
std::memcpy(result.data(), mydata.data(), MYDATA_SIZE);
return result;
}
int main() {
std::clock_t start;
start = std::clock();
auto ret1 = copyDataFromProcess("./test2");
std::cout << "Copy From Process: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << " ms" << std::endl;
start = std::clock();
auto ret2 = copyDataFromInternal();
std::cout << "Copy From Internal: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << " ms" << std::endl;
start = std::clock();
auto ret3 = makeData();
std::cout << "Make Data Time: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << " ms" << std::endl;
std::cout << std::accumulate(ret1.begin(), ret1.end(), 0) << " " << ret1.size() << std::endl;
std::cout << std::accumulate(ret2.begin(), ret2.end(), 0) << " " << ret2.size() << std::endl;
std::cout << std::accumulate(ret3.begin(), ret3.end(), 0) << " " << ret3.size() << std::endl;
return 0;
}
// g++ -std=c++11 -O3 test.cpp -o test
Результаты:
Copy From Process: 718.696 ms
Copy From Internal: 1104.66 ms
Make Data Time: 868.188 ms
2092103051 100000000
-638719098 100000000
-1973221745 100000000