[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [condor-users] intel fortran compiler



Philip Blood wrote:
> Does anyone have a feel for how much work it would take to get Condor to 
> compile with the intel fortran compiler (with full functionality)?  Our 
> codes run much faster on our p4s using the intel compiler compared to pgf90.

Hi Phil,

The problem is that the intel compiler creates threaded code. If you want to
compile and run in the vanilla universe that is no problem, but you'll have
problems compiling in the standard universe as condor checkpointing doesn't
support threaded code.

I have managed to get code linked agains the Intel Math Kernel library to
condor_compile by creating a fake POSIX thread library and linking my code
against that insted. Setting the environment variables

KMP_LIBRARY=serial
MKL_SERIAL=yes

tells the Intel code to run single threaded. My fake thread library provides
only the function that MKL calls. You should be able to do a similar thing for
code built with the Intel compiler but I haven't tried this yet. I've attached
my fake library for you to take a look at.

Cheers,
Duncan.

-- 
Duncan Brown                                  University of Wisconsin-Milwaukee
duncan@xxxxxxxxxxxxxxxxxxxx                 Physics Department, 1900 E. Kenwood
http://www.lsc-group.phys.uwm.edu/~duncan              Milwaukee, WI 53211, USA
/*----------------------------------------------------------------------- 
 * 
 * File Name: qthread.c
 *
 * Author: Brown, D. A.
 * 
 * Revision: $Id: qthread.c,v 1.4 2004/03/30 03:41:07 duncan Exp $
 * 
 *-----------------------------------------------------------------------
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <bits/local_lim.h>

/* lal debug flag for verbosity level */
extern int lalDebugLevel;

/* dummy symbol to ensure that we link this to the fft routines */
int dummy_have_qthread;

/* the following functions are needed to resolve symbols in     */
/* executables linked to the Intel Math Kernel Library DFT      */
/* routines. The function have an implementation that should    */
/* work as long as they are not actually run in threadded       */
/* code. These routines are called by the DFT routines          */
/* during execution, even if the MKL environment variable       */
/* MKL_SERIAL=YES                                               */

/* once-only execution */
enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 };

int pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
{
  /* call the function init_routine() if once_control is not set to done */
  if ( lalDebugLevel & 4 )
    fprintf( stdout, "calling pthread_once(%p,%p)\n", 
        once_control, init_routine );

  if ( *once_control == DONE ) return 0;
  init_routine();
  *once_control = DONE;
  return 0;
}

/* thread specific keys */
typedef void (*destr_function)(void *);

struct pthread_key_struct
{
  int in_use;                   /* already allocated? */
  destr_function destr;         /* destruction routine */
};

/* table of keys */
static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] =
{ { 0, NULL } };

/* value in keys */
static void * pthread_key_values[PTHREAD_KEYS_MAX];

/* create a new key */
int pthread_key_create (pthread_key_t * key, destr_function destr)
{
  int i;

  if ( lalDebugLevel & 4 )
    fprintf( stdout, "calling pthread_key_create(%p,%p)\n", key, destr );

  for ( i = 0; i < PTHREAD_KEYS_MAX; i++ ) 
  {
    if (! pthread_keys[i].in_use) 
    {
      /* Mark key in use */
      pthread_keys[i].in_use = 1;
      pthread_keys[i].destr = destr;
      *key = i;

      /* set the value of the key to null */
      pthread_key_values[i] = NULL;

      return 0;
    }
  }
  return EAGAIN;
}

/* delete a key */
int pthread_key_delete(pthread_key_t key)
{
  if ( lalDebugLevel & 4 )
    fprintf( stdout, "calling pthread_key_delete(%d)\n", key );

  if ( key >= PTHREAD_KEYS_MAX || ! pthread_keys[key].in_use ) 
  {
    return EINVAL;
  }

  pthread_keys[key].in_use = 0;
  pthread_keys[key].destr = NULL;

  /* set the value of the key to null */
  pthread_key_values[key] = NULL;

  return 0;
}

/* set key value */
int pthread_setspecific(pthread_key_t key, const void * pointer)
{
  if ( lalDebugLevel & 4 )
    fprintf( stdout, "calling pthread_setspecific(%d,%p)\n", key, pointer );

  if ( key >= PTHREAD_KEYS_MAX || ! pthread_keys[key].in_use )
  {
    return EINVAL;
  }
  pthread_key_values[key] = (void *) pointer;

  return 0;
}

/* get key value */
void * pthread_getspecific(pthread_key_t key)
{
  if ( lalDebugLevel & 4 )
    fprintf( stdout, "calling pthread_getspecific(%d)\n", key );

  if ( key >= PTHREAD_KEYS_MAX || ! pthread_keys[key].in_use ) 
  {
    return NULL;
  }

  return pthread_key_values[key];
}


/* these functions are needed to resolve the symbols when       */
/* linking in the DFT routines from the Intel Math Kernel       */
/* Library but are not actually called during execution if      */
/* the environment variable MKL_SERIAL=YES. They throw an       */
/* abort() since there is no implementation defined here.       */

int pthread_cancel(pthread_t thread)
{
  fprintf( stderr, "attempt to call pthread_cancel(%ld)\n", thread );
  abort();
  return 0;
}

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void * (*start_routine)(void *), void *arg)
{
  fprintf( stderr, "attempt to call pthread_create(%p,%p,%p,%p)\n",
      thread, attr, start_routine, arg );
  abort();
  return 0;
}

int pthread_join(pthread_t thread_id, void ** thread_return)
{
  fprintf( stderr, "attempt to call pthread_join(%ld,%p)\n", 
      thread_id, thread_return );
  abort();
  return 0;
}

int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask)
{
  fprintf( stderr, "attempt to call pthread_sigmask(%d,%p,%p)\n",
      how, newmask, oldmask );
  abort();
  return 0;
}