我会选择具有混合共享/分布式内存扭曲的选项二......我假设集群中的 13 台机器都访问相同的共享文件系统,并且每台计算机都有足够的内存来加载 8 个问题。
您的代码可能看起来像这样:
int fd, next_task = 0, my_task, nr_tasks;
/* Open the file you want to use to synchronize the nodes. */
if ( ( fd = open( "sharedlockfile" , O_CREAT ) ) < 0 ) {
printf( "failed to create lock file.\n" );
abort();
}
/* Initialize the curr_task in the file. */
if ( <I am the first node in this cluster!> )
if ( write( fd , &next_task , sizeof(int) ) < 0 ) {
printf( "failed to write to lock file." );
abort();
}
/* Main parallel loop. */
#pragma omp parallel shared(fd,next_task), private(mytask)
while ( next_task < nr_tasks ) {
/* Try to get a hold of the lock file, grab a task, and write the new counter. */
#pragma omp critical
{
/* Get a hold of the file lock (this will block until the file is free). */
if ( flock( fd , LOCK_EX ) < 0 ) {
printf( "file locking failed.\n" );
abort(); // not sure I'm allowed to abort in a parallel block...
}
/* Read the index of the next task. */
if ( lseek( fd , 0 , SEEK_SET ) < 0 || read( fd , &next_task , sizeof(int) ) < 0 ) {
printf( "error reading next task id.\n" );
abort();
}
/* Remember my task and update the counter. */
my_task = next_task;
next_task += 1;
/* Write the index of the next task back to the file. */
if ( lseek( fd , 0 , SEEK_SET ) < 0 || write( fd , &next_task , sizeof(int) ) < 0 ) {
printf( "error writing next task id.\n" );
abort();
}
/* Let go of the file. */
if ( flock( fd , LOCK_UN ) < 0 ) {
printf( "file un-locking failed.\n" );
abort();
}
} /* end of critical section */
/* Did we get a valid task ID? */
if ( my_task < nr_tasks ) {
/*
* Do whatever this task implies.
*/
} /* check if valid task ID. */
} /* Main loop. */
请注意,我没有测试过上面的代码!我以前做过类似的事情,其中大部分都在我的脑海中......查看手册页flock以确定。
如果集群中的所有节点都执行此操作,则它们每个都应该生成与它们拥有的内核一样多的线程(或与您在 OMP_NUM_THREADS 中指定的一样多),并且每个内核都将尝试获取一个任务 ID。访问权限next_task在两个级别上进行控制:
- 这样,同一节点上的
#pragma omp critical任何两个线程都不会尝试同时弄乱该next_task变量。
- 通过独占文件锁使得没有两个节点同时读取/更新
next_task存储在文件中的变量。
这应该为您的计算提供良好的、自适应的、动态的调度。
编辑
嗯,锁定可能不像我想象的那么容易,因为它似乎依赖于 fd,因此可能无法跨节点工作。不过,这里似乎有一个很好的解决方案。
附录
如果在单独的内核上解决每个系统对您的内存总线来说压力太大,例如,您注意到它根本无法很好地扩展,您可能想尝试MAGMA,它类似于 LAPACK,但在多核架构上可以很好地扩展。