【问题标题】:Increasing program speedup when using shared memory使用共享内存时提高程序速度
【发布时间】:2016-07-02 20:18:11
【问题描述】:

我有一个程序可以根据 Chudnovsky 公式计算 Pi。它是用 Java 编写的,它使用一个共享向量,用于保存包含元素索引的阶乘和幂等中间计算。

但是,我相信由于它是一个同步向量(默认情况下是线程安全的),因此只有一个线程可以读取或写入它。所以当我们有很多线程时,我们会看到计算时间变得恒定,而不是增加加速。

我可以做些什么来规避这种情况吗?读取/写入同一共享内存的线程过多怎么办?

【问题讨论】:

    标签: java multithreading parallel-processing


    【解决方案1】:

    当访问模式是大量读取和偶尔写入时,您可以使用ReentrantReadWriteLock 保护未同步的数据结构。它允许多个读取器,但只允许一个写入器。

    根据您的实施,您可能还可以从使用ConcurrentHashMap 中受益。

    可能可以作弊并使用AtomicIntegerArrayAtomicReferenceArrayFutures/CompletionStages

    【讨论】:

    • HashMap 真是个好主意。我完全忘记了这一点,当时它显然是存储我已经计算过的大部分内容的完美选择
    【解决方案2】:

    将每个线程的结果存储在堆栈中。一个线程从每个线程收集结果并将它们加在一起。当然栈不应该是空的。

    如果您希望多个线程处理阶乘,为什么不创建一个或两个线程来生成阶乘结果列表。如果需要,其他线程可以只查找结果。

    【讨论】:

    • 这是一个很好的答案,但这并不能完全解决我的问题。正如您从 Wikipedia 中看到的,Chudnovsky 公式中有阶乘。所以所有线程都必须有权访问一些计算这些阶乘的共享内存/向量。当一个线程计算一些大的阶乘时,其他线程将需要访问该线程来计算更多的阶乘等等。
    • 我扩展了我的帖子。
    • 创建阶乘结果列表是什么意思?其他线程依赖于那些计算公式元素的阶乘。另外,没有办法保证阶乘的计算速度比公式中的元素要快...
    • 一个线程计算阶乘并将结果存储在一个可以被其他线程访问的列表中。由于计算阶乘不能并行完成,如果计算速度太慢,那就是极限了。但这可能不会发生,因为计算公式需要多次运算,而再计算一个阶乘意味着乘一次。
    【解决方案3】:

    您可以在堆栈中拥有多个线程和单独的内存,而不是拥有相同的共享内存。最终,用一个线程将所有这些(或偶尔)加起来!

    【讨论】:

    • 不要只是抄袭别人的答案。
    • 哦,刚刚注意到了。我正在输入我的答案,而我猜你只是发布了它并且我没有费心检查。
    • 哦,我以为你只是复制粘贴它并更改了措辞。
    【解决方案4】:

    如果需要高吞吐量,可以考虑使用 Disruptor 和 RingBuffer。

    在粗略的层面上,您可以将 Disruptor 视为队列的多播图,其中生产者将对象放在其上,这些对象通过单独的下游队列发送给所有消费者以供并行消费。当你往里面看时,你会发现这个队列网络实际上是一个单一的数据结构——一个环形缓冲区。

    每个生产者和消费者都有一个序列计数器来指示它当前正在处理缓冲区中的哪个槽。每个生产者/消费者写入自己的序列计数器,但可以读取其他的序列计数器

    几个有用的链接:

    https://lmax-exchange.github.io/disruptor

    http://martinfowler.com/articles/lmax.html

    https://softwareengineering.stackexchange.com/questions/244826/can-someone-explain-in-simple-terms-what-is-the-disruptor-pattern

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多