并行处理for循环

| 我有一个for循环,迭代ѭ0的计算不依赖于先前迭代中的计算。 我想并行化
for
循环(我的代码在Java中),以便可以在多个处理器上同时运行多个迭代的计算。我是否应该为每个迭代的计算创建一个线程,即要创建的线程数等于迭代数(for循环中的迭代数很大)?这该怎么做?     
已邀请:
这是一个小示例,您可能会发现对开始并行化很有帮助。它假定: 您将创建一个“ 2”对象,其中包含您每次计算迭代的输入。 您将创建一个“ 3”对象,其中包含计算每次迭代输入的输出。 您想一次传递一个输入列表,然后一次返回一个输出列表。 您的输入是要做的合理工作,因此开销不会太高。 如果您的计算真的很简单,那么您可能要考虑分批处理它们。您可以在每个输入中输入100。它使用的线程数与系统中处理器的数量相同。如果您要处理的仅仅是CPU密集型任务,那么可能就是您想要的数量。如果他们被阻止等待其他东西(磁盘,网络,数据库等),则希望更高
public List<Output> processInputs(List<Input> inputs)
        throws InterruptedException, ExecutionException {

    int threads = Runtime.getRuntime().availableProcessors();
    ExecutorService service = Executors.newFixedThreadPool(threads);

    List<Future<Output>> futures = new ArrayList<Future<Output>>();
    for (final Input input : inputs) {
        Callable<Output> callable = new Callable<Output>() {
            public Output call() throws Exception {
                Output output = new Output();
                // process your input here and compute the output
                return output;
            }
        };
        futures.add(service.submit(callable));
    }

    service.shutdown();

    List<Output> outputs = new ArrayList<Output>();
    for (Future<Output> future : futures) {
        outputs.add(future.get());
    }
    return outputs;
}
    
您不应该手动执行线程处理。代替: 创建一个大小合理的线程池执行程序服务(如果您的计算没有IO,请使用与内核一样多的线程)。 运行一个循环,将每个单独的计算提交给执行者服务,并保留结果“ 5”个对象。请注意,如果每个计算仅包含少量工作,则这将产生大量开销,甚至可能比单线程程序慢。在这种情况下,请提交执行mdma建议的计算数据包的作业。 运行第二个循环,收集所有ѭ5的结果(它将隐式等待所有计算完成) 关闭执行程序服务     
不,您不应该为每个迭代创建一个线程。线程的最佳数量与可用处理器的数量有关-线程太多,并且您浪费太多时间进行上下文切换而没有增加性能。 如果您不完全依赖Java,则可能要尝试使用并行高性能C系统,例如OpenMPI。 OpenMPI适用于此类问题。     
不要自己创建线程。我建议您使用fork / join框架(jsr166y)并创建可在给定范围内迭代的任务。它会使用与硬件支持一样多的线程来为您管理线程。 任务粒度是这里的主要问题。如果每个迭代的计算量相对较低(例如少于100个操作),那么将每个迭代作为单独的任务执行将带来大量的任务调度开销。最好让每个任务接受要计算的参数列表,然后将结果作为列表返回。这样,您可以使每个任务计算1、10或数千个元素,以使任务的粒度保持在合理的水平,从而平衡了保持工作的可用性和减少任务管理的开销。 jsr166z中还有一个ParallelArray类,该类允许对数组进行重复计算。如果您正在计算的值是原始类型,那么这可能对您有用。     

要回复问题请先登录注册