c++ - 哪些策略可以有效地处理异构多核架构上的并发读取?

标签 c++ multithreading boost concurrency

我正在应对同时使用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/

相关文章:

c++ - std::unordered_map - 如何随时获取 "track"最大/最小键

c++ - 无法在windows上编译WxWidget项目

java - 守护线程比普通线程轻吗?

multithreading - intellij-不在多线程代码中的所有断点上停止

java - Jedis(Redis)减速

c++ - 使用派生单位的计算

c++ - boost::gil 指向 bgr8_view_t 对象的指针

c++ - Qt5.2 QNetwork,写入了多少字节?

c++ - 我的二进制转换器有问题

c++ - 在测试工具中覆盖默认代码的优雅方式