编辑:' Z Boson' Chiron'和' Mattias F'可能正是我需要的。但是,我不知道任何C或C ++是OPENMP和JNI的要求。 OpenCL确实有现有的第三方Java API,但我不知道GPU对我的需求有多高效。我在这里找到了一个有趣的解决方案:Parallelizing a for loop,但这会将我的计算时间减少多个小时吗?
我最终将实现C ++方法,但是现在我需要快速修复。还有其他建议吗?
我遇到一个问题,我需要在n个元素的所有2 ^ n个组合中迭代一系列操作,其代码可以在这里找到:https://stackoverflow.com/questions/26577172/brute-force-optimally-deleting-2s-from-a-random-matrix-how-can-i-make-it-fas。
在我弄清楚随机矩阵背后的数学之前,我想尽可能地优化当前流程,因为即使在通过命令行配置我的Java JVM(热点)以获得高吞吐量之后,在n = 24内迭代也需要数小时。因此,如果我要在所有四个CPU内核中实现多处理/并行计算,这是否会大大缩短完成时间?
我问,因为我对多处理/线程及其实现一无所知,而且只是在java的第一学期入门课程中。如果不明智,我不想浪费时间学习这个。具体来说,在这种情况下(根据我迄今为止在S.O.上所读到的内容),我至少会提交' n'批量作业,其中每批最多包含' x< ñ'来自n的元素为某些x。建议?
答案 0 :(得分:1)
我建议使用JNI和OPENMP构建一个简单的并行环境,自VM机制 无论如何都不能匹配本机代码速度(如C / C ++)。
JNI是一个java功能,它允许您在java中调用c过程。
openmp(omp)是一个c / c ++库,它使并行计算变得非常简单。
而且,JNI是一个非常重要的Java功能,并没有被告知。
对于jni,请访问
http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html
对于omp pdf-docs,请访问
http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf
最后,您的实现可能看起来像这样:
calcu.java
calcu.h
calcu.c
calcu.java:
//If this is a function in your class
public native float calculate(some parameters...); //without implementation in java
calcu.h:
//generated by "javah" command automatically
//some thing above ommitted
JNIEXPORT float JNICALL Java_test_calculate(JNIEnv *, jclass, jbyteArray, jbyteArray);
// has this function declared in c automatically
calcu.c:
#include "calcu.h"
#include "omp.h"
//implement the java native call here
JNIEXPORT float JNICALL Java_test_calculate(JNIEnv *, jclass, jbyteArray, jbyteArray)
{
...some code;
/*Here for example, we use a omp compile command for parallel loop*/
#pragma omp parallel for
for(...)
{} //this for will be automatically executed using parallel computing
}
此外,上面的任务也可以在eclipse java项目中完成。 您可以在eclipse中将java项目转换为C / C ++ Make-file项目,并为jni使用gcc / g ++构建链。这样可以减轻您在终端上输入的大量工作。
================================= CUTCUTCUTCUTCUT ============= ========================
对于那些不希望他们的Java代码被C / C ++弄乱的人,以下建议可能会有用:
据我所知,IBM .Cor引入了一种名为“Threads flood”的编码模式。 该策略的关键思想是在并行程序期间创建尽可能多的线程,以达到VM本机任务调度性能的极限。
演示应该是这样的:
import java.lang.*;
import java.util.regex.*;
import java.util.*;
public class test{
public test()
{
super();
}
public static void main(String[] arg)
{
ResultJoin rj=new ResultJoin();
for(int i=0;i<10;i++)
{
Task t=new Task(1.0*i,2.0*i);
new Emmitable(rj,t).start();
}
System.out.println(rj.getReuslt());
return;
}
}
interface TaskInterface
{
public double calcu();
}
interface ResultInterface
{
public void pushResult(double dat);
public double getReuslt();
}
class Emmitable extends Thread
{
private ResultInterface result=null;
private TaskInterface task=null;
public Emmitable(ResultInterface rj,TaskInterface tsk)
{result=rj;task=tsk;}
public void run()
{
result.pushResult(task.calcu());
}
}
class ResultJoin implements ResultInterface
{
private double sum=0;
public ResultJoin()
{}
public synchronized void pushResult(double i)
{
sum+=i;
}
public synchronized double getReuslt()
{
double result=sum;
return sum;
}
}
class Task implements TaskInterface
{
private double a;
private double b;
public Task(double na,double nb)
{
a=na;b=nb;
}
public double calcu()
{
return 1.0*a*b;
}
}
代码的直观效果是设置一堆线程“On Fly”并将其结果收集到一个地方。
何时使用此模式更好?
当你的每个并行结构非常复杂时(不像'sum + = i'),这种模式将提供相当大的性能。
但是如果你的并行任务就像'sum = sum + i * j'一样简单,那么直接执行它就没有任何并行实际上更好。因为,在微范围内,“new Object()。start()”比几行的简单任务需要更长的时间。
答案 1 :(得分:1)
好的,经过几天的努力,我的代码在快速运行3000次后重新编写代码。我现在可以在5秒内完成2 ^ 24种组合,在2.5小时内完成2 ^ 34种组合。可以在以下位置找到此解决方案的代码:
https://softwareengineering.stackexchange.com/questions/260970/improving-efficiency-of-code
为了“并行化”我的代码,我使用了ExecutorService和InvokeAll。如果有人有任何问题,我会很乐意提供帮助!我通过在线资源自学这一切。
class StringTask implements Callable<Integer> {
private List<List<Integer>> matTan;
private List<int[]> combination;
private List<int[]> jobs;
private boolean gumDrop;
private int minimum;
StringTask(List<int[]> a, List<int[]> b, List<List<Integer>> c, int d, boolean e) {
this.combination = b;
this.minimum = d;
this.gumDrop = e;
this.matTan = c;
this.jobs = a;
}
public Integer call() {
for (int[] e : jobs) {
//Process my data
}
}
return null;
}
}
和(在我的主方法中调用Search.finalize的地方)
class Search {
public static void finalize(List<List<Integer>> matTan, boolean gumDrop, int minimum) {
//Process data
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
List<List<int[]>> ranTime = new ArrayList<List<int[]>>(2 * threads);
for (int x = 0; x < 2 * threads; x++) {
List<int[]> jobs = new ArrayList<int[]>(90);
ranTime.add(jobs);
}
while (condition) {
//Process more data (create the Collections in ranTime)
if (condition) {
processInputs(ranTime, combination, matTan, service);
}
}
service.shutdown();
}
private static void processInputs(List<List<int[]>> ranTime, List<int[]> combination, List<List<Integer>> matTan, ExecutorService service) {
Collection<StringTask> collection = new ArrayList<StringTask>(ranTime.size());
for (List<int[]> jobs : ranTime) {
StringTask analysis = new StringTask(jobs, combination, matTan);
collection.add(analysis);
}
try {
List<Future<Integer>> futures = service.invokeAll(collection);
} catch (Exception e) {
e.printStackTrace();
}
}