私は、ハードディスク上の大きなフロートセットのシリアライゼーションを最適化するタスクを持っています。 私の最初のアプローチは、以下があります。大量の浮動小数点数のcentOS上の文字列シリアル化は、チャンクを直列化する4個のpthread-tよりも高速です。 Windowsでstd :: threadsが高速になっています
class StringStreamDataSerializer
{
public:
void serializeRawData(const vector<float>& data);
void saveToFileStream(std::fstream& file);
private:
stringstream _stringStream;
};
void StringStreamDataSerializer::serializeRawData(const vector<float>& data)
{
for (float currentFloat : data)
_stringStream << currentFloat;
}
void StringStreamDataSerializer::saveToFileStream(std::fstream& file)
{
file << _stringStream.str().c_str();
file.close();
}
私は速く シリアル化を行うために、4つのスレッド間serializatonのタスクを分離したかったです。方法は次のとおりです。
struct st_args
{
const vector<float>* data;
size_t from;
size_t to;
size_t segment;
} ;
string outputs[4];
std::mutex g_display_mutex;
void serializeLocal(void *context)
{
struct st_args *readParams = (st_args*)context;
for (auto i = readParams->from; i < readParams->to; i++)
{
string currentFloat = std::to_string(readParams->data->at(i));
currentFloat.erase(currentFloat.find_last_not_of('0') + 1,
std::string::npos);
outputs[readParams->segment] += currentFloat;
}
}
void SImplePThreadedSerializer::serializeRawData(const vector<float>& data)
{
const int N = 4;
size_t totalFloats = data.size();
st_args* seg;
pthread_t* chunk;
chunk = (pthread_t *) malloc(N*sizeof(pthread_t));
seg = (st_args *) malloc(N*sizeof(st_args));
size_t from = 0;
for(int i = 0; i < N; i++)
{
seg[i].from = 0;
seg[i].data = &data;
}
int i = 0;
for (; i < N - 1; ++i)
{
seg[i].from = from;
seg[i].to = seg[i].from + totalFloats/N;
seg[i].segment = i;
pthread_create(&chunk[i], NULL, (void *(*)(void *)) serializeLocal,
(void *) &(seg[i]));
from += totalFloats/N;
}
seg[i].from = from;
seg[i].to = totalFloats;
seg[i].segment = i;
pthread_create(&chunk[i], NULL, (void *(*)(void *)) serializeLocal, (void *)
&(seg[i]));
size_t totalBuffered = 0;
for (int k = 0; k < N; k++)
{
pthread_join(chunk[k], NULL);
totalBuffered += outputs[k].size();
}
str.reserve(totalBuffered);
for (int k = 0; k < N; k++)
{
str+= outputs[k];
}
free(chunk);
free(seg);
}
Linuxでは、文字列ストリームが4つのスレッドより速いことが判明しました。 Windowsでは、Windows上で提示された方法(std :: threadを使用)で最適化をアーカイブしていますが、Linuxでは逆の結果が得られます。どのような説明が有用であり、評価されるのか?ハードディスク上の10000000台の山車の *シリアル* 0.55秒で、ファイル内 StringStreamDataSerializerのフラッシュデータ:ここ
はCentOSの上の結果があります。 StringStreamDataSerializer 3.28秒で終了しました。 SImplePThreadedSerializerは、0.46秒でファイル内のデータをフラッシュします。 SImplePThreadedSerializer 6.96秒で終了しました。
Windows上、マルチスレッドのシリアル化が4つのstd ::スレッドで実行され、彼らが実際にシリアル化を最適化する:
static void serializeChunk(string& output, const vector<float>& data, size_t
from, size_t to)
{
for (auto i = from; i < to; i++)
{
string currentFloat = std::to_string(data[i]);
//fuckin trim the zeroes at the end
currentFloat.erase(currentFloat.find_last_not_of('0') + 1,
std::string::npos);
output += currentFloat;
}
}
void SimpleMultiThreadedSerializer::serializeRawData(const vector<float>&
data)
{
const int N = 4;
thread t[N]; // say, 4 CPUs.
string outputs[N];
size_t totalFloats = data.size();
size_t from = 0;
int i = 0;
for (; i < N - 1; ++i)
{
t[i] = thread(serializeChunk, std::ref(outputs[i]), data, from, from +
totalFloats/N);
from += totalFloats/N;
}
t[i] = thread(serializeChunk, std::ref(outputs[i]), data, from,
totalFloats);
for (i = 0; i < N; ++i)
t[i].join();
size_t totalBuffered = 0;
for (int i = 0; i < N; ++i)
totalBuffered += outputs[i].size();
str.reserve(totalBuffered);
for (int i = 0; i < N; ++i)
str += outputs[i];
}
と結果:ハードディスク上の1000000台の山車の *シリアル* StringStreamDataSerializerは、0.116秒でファイル内のデータをフラッシュします。 StringStreamDataSerializer 10.236秒で終了しました。
SimpleMultiThreadedSerializerは、0.105秒でファイル内のデータをフラッシュします。 SimpleMultiThreadedSerializer 3.01秒で終了しました。
返信いただきありがとうございます!私はその問題を理解していると思う。私は、ftoaメソッドを実装して使用しようとします。ftoaメソッドはロケールオブジェクトを取得し、ロックするか、まったく使用しません。 – GeorgiF