我已经将一个巨大的文件映射到char字符串中并从中创建了一个c ++字符串。我需要根据一个空格字符的分隔字符解析这个字符串,并将值存储在矩阵中。我可以从一个线程做到但我需要优化它。所以我使用多个线程来解析来自这个sstream的字符串并将其存储在矩阵中。虽然基于线程id,但我可以将解析后的数据同步存储到矩阵中但是我如何同步解析,因为任何线程都可以随时调度并解析字符串。这是我的代码
void* parseMappedString(void* args)
{
char temp[BUFFSIZE];
long int threadID = *((long int*)args);
if (threadID < 0)
threadID = 0;
for (int i = ((threadID) * 160); i < ((threadID+1) * 160); i++)
{
for (int j = 0; j < 4000; j++)
{
pthread_mutex_lock(&ParseMatrixMutex);
if ((matrix_str.getline(temp,BUFFSIZE, ' ')) )
{
pthread_mutex_unlock(&ParseMatrixMutex);
matrix[i][j] = parseFloat((temp));
}
else
{
pthread_mutex_unlock(&ParseMatrixMutex);
}
}
}
}
void create_threads_for_parsing(void)
{
long int i;
for (i = 0; i < 5; i++)
pthread_create(&Threads[i], NULL, parseMappedString, (void*)&i);
}
在代码中,如果您看到总共有五个线程,并且每个线程正在处理160 * 4000个元素。并且它们基于其线程ID存储,因此进入矩阵中的唯一位置。所以它是同步的方式。但getline可以在任何时候由任何线程完成,因此5号线程可以解析属于第一个线程的数据。我该如何避免这种情况?
我必须遵循因为我在args中接收1-4个threadids但从不接收0.它总是以一些垃圾负值而来,因此我不得不像这样硬编码。
if(threadID&lt; 0) threadID = 0;
答案 0 :(得分:1)
我已经将一个巨大的文件映射到char字符串并制作了一个c ++字符串
不要,std::string
必须复制内存,因此你会失去性能提升mmap否则会得到你。只需将原始内存作为char数组
我可以从一个线程做到但我需要优化它
您确定多个线程将优化它吗?你是否有资料并确认它绝对是CPU限制而不是I / O限制?
如果您确定要使用多个线程,我建议您这样做:
至于代码中的错误我试图说服你不要使用:你将(void*)&i
作为你的参数传递给线程函数。这是一个指向create_threads_for_parsing
末尾超出范围的自动局部的指针,所以当任何线程读取它时,它可能是随机垃圾。
即使它不是 random 垃圾(即,如果create_threads_for_parsing
在返回之前加入所有线程,保持i
在范围内),它将相同每个线程的指针。
为了安全地向每个线程传递一个不同的整数id,你应该为每个线程分配一个不同的整数,并传递它的地址。这可能是intptr_t
或其他问题。
答案 1 :(得分:0)
std::string::getline
不是线程安全的,您不能使用来自不同线程的getline()
。
您需要使用strncopy(c-style)访问内存中原始字符串数据中的已知位置
strncopy(matrix_str.c_str(), temp, 4000);
或使用substring-function(C ++风格)
std::string piece = matrix_str.substr(i,4000)
编辑:如果您的matrix_str
不是std::string
而是std::sstream
对象,则无法按顺序访问流。你的问题在这方面有点模糊......
答案 2 :(得分:0)
代码几乎完全是互斥的 - 因此使用线程毫无意义。
腭化的想法是允许实际上同时完成工作。为此,您应减少数据共享,理想情况下为零。
就像将大字符串分成前面的4个部分并将其发布到线程一样,这样他们就可以读取和处理它,将结果放在它们的专属位置。如果没有共享单元格,输出可以转到矩阵,但要注意false sharing
仍可能破坏性能。
答案 3 :(得分:0)
在奇怪的0 ID部分:我认为发布的代码只是演示,但你可能会像字面意思那样。
在离开函数create_threads_for_parsing之前,必须加入所有线程。目前您传递给指向其中的局部变量的线程指针。
更糟糕的是,变量是共享的,因此你有一个竞争条件。你做了类似的事情:
static const int ids = {0, 1, 2, 3, 4};
并将指针传递给循环中的正确单元格。