我正在应对同时使用8 核 机器和高端GPU (Tesla 10) 功能的挑战。
我有一个大输入文件,每个内核一个线程,一个用于 GPU 处理。 Gpu 线程为了高效,需要大量的输入行,而 Cpu 线程只需要一行继续(在临时缓冲区中存储多行速度较慢)。该文件不需要按顺序读取。我正在使用 boost。
我的策略是在输入流上有一个互斥锁,每个线程锁定 - 解锁它。 这不是最优的,因为 gpu 线程在锁定互斥锁时应该有更高的优先级,是最快和最苛刻的线程。
我可以想出不同的解决方案,但在匆忙实现之前,我希望有一些指导方针。
您使用/推荐什么方法?
最佳答案
如果“每个线程 1 行”不是严格要求,您可能根本不需要锁定,有时您可以达到 2 行或 3 行。然后,您可以根据公式平均拆分文件。假设您想要读取总共 1024 KB block 中的文件(这也可能是千兆字节):您将其拆分为具有优先级的核心。所以:
#define BLOCK_SIZE (1024 * 1024)
#define REGULAR_THREAD_BLOCK_SIZE (BLOCK_SIZE/(2 * NUM_CORES))//64kb
#define GPU_THREAD_BLOCK_SIZE (BLOCK_SIZE/2)
- 每个核心获得 64 KB block
- 核心 1:偏移量 0,大小 = REGULAR_THREAD_BLOCK_SIZE
- 核心 2:偏移量 65536,大小 = REGULAR_THREAD_BLOCK_SIZE
- 核心 3:偏移量 131072,大小 = REGULAR_THREAD_BLOCK_SIZE
- 核心 n:偏移量
(n * REGULAR_THREAD_BLOCK_SIZE)
,大小 =REGULAR_THREAD_BLOCK_SIZE
- GPU 获得 512 KB,偏移量 =
(NUM_CORES * REGULAR_THREAD_BLOCK_SIZE)
,大小 =GPU_THREAD_BLOCK_SIZE
因此理想情况下它们不会重叠。但在某些情况下它们可以重叠。由于您正在读取文本文件,因此一行可能会落入下一个核心的 block 中。为避免重叠,您总是跳过其他内核的第一行,并始终完成最后一行,假设下一个线程无论如何都会跳过它,这是伪代码:
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
}
如您所见,这并行化了读取 block 的处理,而不是读取本身。你如何并行化读取?最好最棒的方法是将整个 block 内存映射到内存中。这将获得最佳的 I/O 性能,因为它是最低级别。
关于c++ - 哪些策略可以有效地处理异构多核架构上的并发读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2643837/