我正在研究一台8核机器,并且正在执行计算量很大的任务。然而,任务的每次执行(即,for循环的迭代)都与前一个独立。只有一些变量从一个执行到下一个执行“总结”。我猜这是并行/线程的一个很好的例子,但我不知道如何去做。
以下是代码的外观。截至目前,它只是我的主执行器类中主要方法的一部分:
double testerPayoffSum = 0.0, developerPayoffSum = 0.0;
Random seed = new Random();
try {
for (int i = 0; i < GameConstants.MAX_GAMES; i++) {
EraserSimulator eraser = new EraserSimulator(GameConstants.MAX_TARGETS, GameConstants.MAX_RESOURCES, GameConstants.NUM_ATTACKER_TYPES, seed.nextInt());
Map<Set<SingleObjectiveTarget>, Double> gameStrategy = eraser.run();
assert (gameStrategy != null);
TestingGameSimulator testingGame = new TestingGameSimulator(GameConstants.MAX_TARGETS, gameStrategy, GameConstants.NUM_GAMES_TO_STORE_FOR_HISTORY, GameConstants.NUM_TESTING_GAMES_TO_PLAY);
PlayerPayoffs payoffs = testingGame.run(eraser.getEraserInstance());
testerPayoffSum += payoffs.getAverageTesterPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
developerPayoffSum += payoffs.getAverageDeveloperPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
System.out.print("Output: ERASER Games played; Number of developers caught");
System.out.print(", " + GameConstants.NUM_TESTING_GAMES_TO_PLAY + ", " + payoffs.getNumTimesCaught() + "\n");
} catch(Exception e){sendEmailAlert("Execution Failed with Exception");}
如果可能,我想并行for-loop
计算并继续总结testerPayoffSum
和developerPayofffSum
变量。我怎么能实现这个目标?
注意:每次执行for循环大约需要20-30分钟,具体取决于输入大小(由各种GameConstant
设置)。即使是少数MAX_GAMES
,上述时间也要接近2-3小时。
答案 0 :(得分:1)
创建一个实现Callable
的线程对象,该对象返回包含Future
和testerPayoffSum
的{{1}}对象,开始计算并对从{{1}获得的结果求和} s(另见https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6)。
答案 1 :(得分:1)
你绝对确定你没有依赖吗?
1.使用过的类不得共享任何变量
2.使用过的课程不得使用任何机器学习。
现在该怎么做(我不是JAVA编码器所以我坚持使用C ++代码)。
//--- globals and headers -----------------------------------------------------
unsigned long __stdcall function(LPVOID p);
Random seed = new Random();
const int N=8; // threads count (<=CPU count)
int id[N]; // thread id
int max[N]; // number of games per thread
double testerPayoffSum[N]; // sum to separate variables to avoid locks need
double developerPayoffSum[N];
volatile int run=0,stop=0; // thread control variables run is number of running threads and stop force stop...
//--- main code ---------------------------------------------------------------
// init some variables ... may be the seed init will be better here too
int i;
for (i = 0; i < N; i++)
{
id[i]=i;
max[i]=GameConstants.MAX_GAMES / N;
testerPayoffSum[i]=0.0;
developerPayoffSum[i]=0.0;
}
max[0]=GameConstants.MAX_GAMES % N;
// create threads
for (i = 0; i < N; i++)
{
HANDLE hnd=CreateThread(0,0,function,&id[i],0,0);
if (hnd!=NULL) CloseHandle(hnd); // this line is important !!!
// because if you do not close Handle it will be allocated until the end of app
// handle leaks are nasty and cause weird OS behaviour
// I saw many times this bug in commercial drivers
// it is a nightmare for 24/7 software
}
// wait for them
while (run) Sleep(200);
// sum the results to [0]
for (i = 1; i < N; i++)
{
testerPayoffSum[0] +=testerPayoffSum[i];
developerPayoffSum[0]+=developerPayoffSum[i];
}
// here do what you need to do with the results
//--- thread function ---------------------------------------------------------
unsigned long __stdcall function(LPVOID p)
{
run++;
int ix=((int*)p)[0];
for (i = 0; i < max[ix]; i++)
{
if (stop) break;
EraserSimulator eraser = new EraserSimulator(GameConstants.MAX_TARGETS, GameConstants.MAX_RESOURCES, GameConstants.NUM_ATTACKER_TYPES, seed.nextInt());
Map<Set<SingleObjectiveTarget>, Double> gameStrategy = eraser.run();
assert (gameStrategy != null);
TestingGameSimulator testingGame = new TestingGameSimulator(GameConstants.MAX_TARGETS, gameStrategy, GameConstants.NUM_GAMES_TO_STORE_FOR_HISTORY, GameConstants.NUM_TESTING_GAMES_TO_PLAY);
PlayerPayoffs payoffs = testingGame.run(eraser.getEraserInstance());
testerPayoffSum[ix] += payoffs.getAverageTesterPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
developerPayoffSum[ix] += payoffs.getAverageDeveloperPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
// do not call any visual stuff from thread !!! sometimes it can cause a lot of problems ...
// instead cretae some global string variable and set it to what shoud be printed out
// and inside wait while loop in main code add if string != "" then System.out.print(string);
// but in that case you should add lock to it.
// System.out.print("Output: ERASER Games played; Number of developers caught");
// System.out.print(", " + GameConstants.NUM_TESTING_GAMES_TO_PLAY + ", " + payoffs.getNumTimesCaught() + "\n");
//Sleep(100); // well placed sleep
}
run--;
}
[注释]
[锁定]
但你也可以使用自己喜欢的东西
class _lock
{
public:
volatile bool locked;
_lock() { locked=false; }
void lock() { while(locked) Sleep(1); locked=true; }
void unlock() { locked=false; }
};
// now for each shared variable (or group of variables) add one global _lock variable
_lock l1; int sv1; // shared variable 1 and her lock
// any write access and sometimes also read access needs lock
l1.lock();
sv1++;
l1.unlock();
请注意锁定有时会导致App冻结,尤其是在重负荷使用时。
答案 2 :(得分:1)
声明队列以收集结果并将任务提交给线程池:
final ArrayBloclingQueue<PlayerPayoffs> queue=new ArrayBloclingQueue<PlayerPayoffs>();
Executor exec=new Executors.newFixedThreadPool(N); // number of threads depends on hardware
for (int i = 0; i < GameConstants.MAX_GAMES; i++) {
exec.execute(new Runnable(){
EraserSimulator eraser = new EraserSimulator(GameConstants.MAX_TARGETS, GameConstants.MAX_RESOURCES, GameConstants.NUM_ATTACKER_TYPES, seed.nextInt());
Map<Set<SingleObjectiveTarget>, Double> gameStrategy = eraser.run();
assert (gameStrategy != null);
TestingGameSimulator testingGame = new TestingGameSimulator(GameConstants.MAX_TARGETS, gameStrategy, GameConstants.NUM_GAMES_TO_STORE_FOR_HISTORY, GameConstants.NUM_TESTING_GAMES_TO_PLAY);
PlayerPayoffs payoffs = testingGame.run(eraser.getEraserInstance());
queue.put(payoffs);
});
}
然后收集并总结结果:
double testerPayoffSum = 0.0, developerPayoffSum = 0.0;
for (int i = 0; i < GameConstants.MAX_GAMES; i++) {
PlayerPayoffs payoffs=queue.take();
testerPayoffSum += payoffs.getAverageTesterPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
developerPayoffSum += payoffs.getAverageDeveloperPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
System.out.print("Output: ERASER Games played; Number of developers caught");
System.out.print(", " + GameConstants.NUM_TESTING_GAMES_TO_PLAY + ", " + payoffs.getNumTimesCaught() + "\n");
}