【问题标题】:Is mutex needed for different offsets into allocated heap memory分配的堆内存中的不同偏移量是否需要互斥锁
【发布时间】:2016-01-10 00:59:19
【问题描述】:

我正在为一个生成二进制数据表的工具构建框架。我计划制作这个多线程以充分利用我可以使用的 24 个内核。 (我估计在一个线程中生成数据的时间大约为 50 天。)。我过去曾使用带有套接字通信的服务器/客户端设计来完成此操作,因为我需要将其分布在多台机器上。

这一次,我正在研究单机/多线程方法,并试图找出正确的方法。

主线程将处理分配给每个子线程的任务,并确定分配内存的偏移量。

每个线程将写入分配的内存中的唯一地址范围。因为这些块永远不会在记录之间重叠,所以没有两个线程会尝试写入相同的偏移量。

void computeRecord(void *taskInput)
{
  struct TaskData *taskData = (TaskData *)(taskInput);

  RecordData data; 
  // A huge long computation block to populate data
  //   (4-5 second run time)

  long record_id = taskData->record_id;
  char *buffer   = taskData->start_buffer;

  // mutex lock needed here ??

  int n_bytes = sizeof(RecordData)
  memcpy( (char *)(buffer+record_id*n_bytes), (char *)(&recordData) n_bytes);

  // mutex unlock here ?
}

长时间设置。简短的问题。在这种情况下是否需要互斥锁?

【问题讨论】:

  • 我认为不需要,但可能有一些微妙之处,所以我不会回答。
  • 我不希望一个 50 个计算天的任务自己完全存在于内存中。该级别的计算:生成的位应该很容易保存到磁盘而不会损害带宽,这样就可以轻松收集部分运行,并将消耗与生产分开。但是,对于您的问题,如果您的偏移量在大多数架构上合理对齐,则不需要互斥锁。
  • 你有没有想过使用 OpenMP:它正是它旨在解决的那种并行性
  • 什么计算这么慢?只是好奇。
  • @Yakk,请注意,通过 24 核上的多线程,挂钟时间应该下降到更像 2 个真实天。话虽如此,我确实计划每隔一小时左右检查一次我的数据(为此我想我将使用信号量在写出缓冲区之前停止所有线程)。

标签: c++ c multithreading mutex


【解决方案1】:

为了获得最佳性能,您需要将数据与缓存线对齐 - 这将避免不同的 CPU 内核在彼此之间“弹跳”缓存线。

但不管怎样,只要我们谈论的是独立交互的单独字节,就不需要保护。仅当多个线程访问同一个字节时[当然也适用于访问多个字节时]。

编辑:这句话当然只有在处理器有字节寻址时才成立。想到的处理器不是 Alpha,但可能还有其他处理器。 (Edit2:不,在符合 C++11 的编译器中无关紧要,由编译器以线程安全的方式处理字节寻址)

【讨论】:

  • 不幸的是,我无法控制数据表(或其中包含的记录)的结构。我正在为定义数据接口的应用程序生成数据。
  • 您是在断言没有处理器的内存读取/写入一次大于一个字节?
  • @Yakk:正确,我已经添加了一个声明。
  • 在多线程程序中写入两个不同的地址是由标准明确定义的。如果 CPU 不能进行字节寻址,编译器必须担心该怎么做。其他任何事情都会使编写正确的程序成为不可能
  • Question on the topic:目前的共识似乎是编译器负责确保正确处理对不同偏移量的写入。
猜你喜欢
  • 2011-09-06
  • 1970-01-01
  • 2010-09-12
  • 2011-12-01
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多