我正在应对同时使用8核心机器和高端GPU (Tesla 10)的能力的挑战。
我有一个大的输入文件,一个线程为每个核心,一个用于GPU处理。为了提高效率,Gpu线程需要输入大量行,而Cpu线程只需要一行就可以继续工作(在临时缓冲区中存储多行比较慢)。该文件不需要按顺序读取。我正在使用boost。
我的策略是在输入流上有一个互斥锁,每个线程都锁定-解锁。这不是最优的,因为gpu线程在锁定互斥锁时应该具有更高的优先级,因为它是最快的,也是要求最高的。
我可以想出不同的解决方案,但在仓促实施之前,我想有一些指导方针。
你使用/推荐什么方法?
发布于 2010-04-18 10:36:33
如果“每个线程1行”不是一个严格的要求,并且有时可以达到2行或3行,您可能根本不需要锁定。然后,您可以根据公式平分文件。假设您希望以1024千字节块的形式读取该文件(这也可能是千兆字节):将其分割成具有优先级的核心。所以:
#define BLOCK_SIZE (1024 * 1024)#define REGULAR_THREAD_BLOCK_SIZE (BLOCK_SIZE/(2 * NUM_CORES)) // 64kb#define GPU_THREAD_BLOCK_SIZE (BLOCK_SIZE/2)(n * REGULAR_THREAD_BLOCK_SIZE),size = REGULAR_THREAD_BLOCK_SIZE
GPU_THREAD_BLOCK_SIZE
(NUM_CORES * REGULAR_THREAD_BLOCK_SIZE),大小=所以理想情况下它们不会重叠。不过,在某些情况下,它们可以重叠。由于您正在读取文本文件,一行可能会落入下一个核心的块中。为了避免重叠,您总是跳过其他内核的第一行,并且总是完成最后一行,假设下一个线程将跳过它,下面是伪代码:
void threadProcess(buf, startOFfset, blockSize)
{
int offset = startOffset;
int endOffset = startOffset + blockSize;
if(coreNum > 0) {
// skip to the next line
while(buf[offset] != '\n' && offset < endOffset) offset++;
}
if(offset >= endOffset) return; // nothing left to process
// read number of lines provided in buffer
char *currentLine = allocLineBuffer(); // opening door to security exploits :)
int strPos = 0;
while(offset < endOffset) {
if(buf[offset] == '\n') {
currentLine[strPos] = 0;
processLine(currentLine); // do line processing here
strPos = 0; // fresh start
offset++;
continue;
}
currentLine[strPos] = buf[offset];
offset++;
strPos++;
}
// read the remaineder past the buf
strPos = 0;
while(buf[offset] != '\n') {
currentLine[strPos++] = buf[offset++];
}
currentLine[strPos] = 0;
processLine(currentLine); // process the carryover line
}如您所见,这将并行处理读取块,而不是读取本身。如何并行读取?最好的最棒的方法是将整个块映射到内存中。这将获得最好的I/O性能,因为它是最低的水平。
发布于 2010-04-17 20:25:28
一些想法:
1)由于瓶颈不在IO中,为了便于访问,文件应该几乎完全保存在RAM中。
2)实现不应允许线程阻塞。如果这样做可以减少阻塞,那么最好有一些非最优的解决方案。
假设我们有大数据文件,线程可以在黑暗的战术中使用射击。这意味着一旦线程获得锁,它就会增加fpos并解锁内存。然后,它授予自己处理它刚刚获得的内存部分的特权。例如,线程可以处理开始于片段中的所有行。
成果:
1)线程几乎不可能阻塞。锁时间非常短(在几条指令+刷新缓存的时间范围内)
2)灵活性。线程可以接收任意多的数据。
当然,应该有一些机制来适应数据文件中的行长度,以避免出现最坏的情况。
发布于 2010-04-17 02:48:26
我会用缓冲器。让单个线程从磁盘中填充该缓冲区。每个线程将锁定缓冲区,将数据读入线程的缓冲区,然后在处理数据之前释放互斥锁。
https://stackoverflow.com/questions/2643837
复制相似问题