Fast UUID generation in matlab

99 Ansichten (letzte 30 Tage)
Simon Parten
Simon Parten am 29 Apr. 2019
Beantwortet: Philipp Tempel am 17 Mär. 2022
I want to generate some UUIDS.
function ids = makeUUIDs(num)
% idsJ = javaArray('java.util.UUID',num);
ids = strings(num,1);
for i = 1 : num
ids(i) = java.util.UUID.randomUUID;
end
% ids = arrayfun(@(x) string(x), idsJ);
% ids = jstring2string(ids);
end
Unfortunately, this is too slow for my liking
aTest= makeUUIDs(100000);
Takes 19.8 seconds... however, the actual generation in java takes 0.945 seconds according to the profiler. Can anyone thing of a faster way to do this???

Akzeptierte Antwort

Simon Parten
Simon Parten am 18 Okt. 2019
The above was, in the end simply not fast enough. The below generates 1e6 UUIDS into a matlab string array, in 2.6s on my machine.
Much better.
Try this;
#include <iostream>
#include <string>
#include <list>
#include "MatlabDataArray.hpp"
#include "C:/temp/fastUUID/boost_1_71_0/boost_1_71_0/boost/uuid/uuid.hpp" // uuid class
#include "C:/temp/fastUUID/boost_1_71_0/boost_1_71_0/boost/uuid/uuid_generators.hpp" // generators
#include "C:/temp/fastUUID/boost_1_71_0/boost_1_71_0/boost/uuid/uuid_io.hpp" // streaming operators etc.
#include "C:/temp/fastUUID/boost_1_71_0/boost_1_71_0/boost/lexical_cast.hpp" // streaming operators etc.
#include "mex.hpp"
#include "mexAdapter.hpp"
using namespace matlab::data;
using matlab::mex::ArgumentList;
using namespace std;
// You'll need to install https://www.boost.org/
// The matlab cpp compiler
// And finally mex makeUuidArray.cpp -IC:\temp\fastUUID\boost_1_71_0\boost_1_71_0
class MexFunction : public matlab::mex::Function {
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
checkArguments(outputs, inputs);
const int numIds = inputs[0][0];
ArrayFactory factory;
boost::uuids::random_generator generator;
boost::uuids::uuid uuid1;
// Three variables for the string vector, tempstring, tempUUID
TypedArray<MATLABString> results = factory.createArray<MATLABString>({ numIds,1 });
for (auto elem : results) {
uuid1 = generator();
elem = boost::lexical_cast<std::string>(uuid1) ;
}
outputs[0] = results ;
}
void checkArguments(ArgumentList outputs, ArgumentList inputs) {
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
ArrayFactory factory;
// Check first input argument
if (inputs[0].getType() != ArrayType::DOUBLE ||
inputs[0].getType() == ArrayType::COMPLEX_DOUBLE ||
inputs[0].getNumberOfElements() != 1)
{
matlabPtr->feval(u"error",
0,
std::vector<Array>({ factory.createScalar("First input must be scalar double") }));
}
// Check number of outputs
if (outputs.size() > 1) {
matlabPtr->feval(u"error",
0,
std::vector<Array>({ factory.createScalar("Only one output is returned") }));
}
}
};

Weitere Antworten (2)

Philipp Tempel
Philipp Tempel am 17 Mär. 2022
This may be too stupid to be true but, looking at the source code of tempname(), you can see that you can simply do
uuid = char(matlab.lang.internal.uuid())
It's not as fast as @Simon Parten's solution (about one magnitude slower), but it at least doesn't require compiling C-code and it uses only built-in MATLAB functions.
Stats:
Trial1
runs: 1e6
sum: 18s 316.259ms
min: 15.1694mus
median: 17mus
mean: 18mus
max: 702.108402mus
std: 5.847mus

Simon Parten
Simon Parten am 2 Mai 2019
This is my best solution
idsJ = javaArray('java.lang.String',num);
ids = strings(num,1);
for i = 1 : num
idsJ(i) = javaMethod('toString', java.util.UUID.randomUUID);
end
ids = string(idsJ);

Tags

Produkte

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by