首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在异构多核体系结构上处理并发读取的有效策略是什么?

在异构多核体系结构上处理并发读取的有效策略是什么?
EN

Stack Overflow用户
提问于 2010-04-15 08:46:46
回答 3查看 271关注 0票数 3

我正在应对同时使用8核心机器和高端GPU (Tesla 10)的能力的挑战。

我有一个大的输入文件,一个线程为每个核心,一个用于GPU处理。为了提高效率,Gpu线程需要输入大量行,而Cpu线程只需要一行就可以继续工作(在临时缓冲区中存储多行比较慢)。该文件不需要按顺序读取。我正在使用boost

我的策略是在输入流上有一个互斥锁,每个线程都锁定-解锁。这不是最优的,因为gpu线程在锁定互斥锁时应该具有更高的优先级,因为它是最快的,也是要求最高的。

我可以想出不同的解决方案,但在仓促实施之前,我想有一些指导方针。

你使用/推荐什么方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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)
  • Each核获得64 KB块
    • 核1:偏移量0,大小= REGULAR_THREAD_BLOCK_SIZE
    • Core 2:偏移量65536,大小= REGULAR_THREAD_BLOCK_SIZE
    • Core 3:偏移量131072,size = REGULAR_THREAD_BLOCK_SIZE
    • Core n:偏移量(n * REGULAR_THREAD_BLOCK_SIZE),size = REGULAR_THREAD_BLOCK_SIZE

GPU_THREAD_BLOCK_SIZE

  • GPU获得512 KB,偏移量= (NUM_CORES * REGULAR_THREAD_BLOCK_SIZE),大小=

所以理想情况下它们不会重叠。不过,在某些情况下,它们可以重叠。由于您正在读取文本文件,一行可能会落入下一个核心的块中。为了避免重叠,您总是跳过其他内核的第一行,并且总是完成最后一行,假设下一个线程将跳过它,下面是伪代码:

代码语言:javascript
复制
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性能,因为它是最低的水平。

票数 2
EN

Stack Overflow用户

发布于 2010-04-17 20:25:28

一些想法:

1)由于瓶颈不在IO中,为了便于访问,文件应该几乎完全保存在RAM中。

2)实现不应允许线程阻塞。如果这样做可以减少阻塞,那么最好有一些非最优的解决方案。

假设我们有大数据文件,线程可以在黑暗的战术中使用射击。这意味着一旦线程获得锁,它就会增加fpos并解锁内存。然后,它授予自己处理它刚刚获得的内存部分的特权。例如,线程可以处理开始于片段中的所有行。

成果:

1)线程几乎不可能阻塞。锁时间非常短(在几条指令+刷新缓存的时间范围内)

2)灵活性。线程可以接收任意多的数据。

当然,应该有一些机制来适应数据文件中的行长度,以避免出现最坏的情况。

票数 1
EN

Stack Overflow用户

发布于 2010-04-17 02:48:26

我会用缓冲器。让单个线程从磁盘中填充该缓冲区。每个线程将锁定缓冲区,将数据读入线程的缓冲区,然后在处理数据之前释放互斥锁。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2643837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档