* the research papers on the package. Check out http://www.gromacs.org.
*/
+#include "gmxpre.h"
+
+#include "gromacs/legacyheaders/gpu_utils.h"
+
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
+#include "gromacs/gmxlib/cuda_tools/cudautils.cuh"
+#include "gromacs/legacyheaders/types/hw_info.h"
+#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/smalloc.h"
-#include "types/hw_info.h"
-
-#include "gpu_utils.h"
-#include "../cuda_tools/cudautils.cuh"
-#include "memtestG80_core.h"
-
-/** Amount of memory to be used in quick memtest. */
-#define QUICK_MEM 250
-/** Bit flag with type of tests to run in quick memtest. */
-#define QUICK_TESTS MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS
-/** Number of iterations in quick memtest. */
-#define QUICK_ITER 3
-
-/** Bitflag with all test set on for full memetest. */
-#define FULL_TESTS 0x3FFF
-/** Number of iterations in full memtest. */
-#define FULL_ITER 25
-
-/** Bit flag with type of tests to run in time constrained memtest. */
-#define TIMED_TESTS MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS
/*! \brief
* Max number of devices supported by CUDA (for consistency checking).
}
-/** Bit-flags which refer to memtestG80 test types and are used in do_memtest
- * to specify which tests to run. */
-enum memtest_G80_test_types {
- MOVING_INVERSIONS_10 = 0x1,
- MOVING_INVERSIONS_RAND = 0x2,
- WALKING_8BIT_M86 = 0x4,
- WALKING_0_8BIT = 0x8,
- WALKING_1_8BIT = 0x10,
- WALKING_0_32BIT = 0x20,
- WALKING_1_32BIT = 0x40,
- RANDOM_BLOCKS = 0x80,
- MOD_20_32BIT = 0x100,
- LOGIC_1_ITER = 0x200,
- LOGIC_4_ITER = 0x400,
- LOGIC_1_ITER_SHMEM = 0x800,
- LOGIC_4_ITER_SHMEM = 0x1000
-};
-
-
/*!
* \brief Runs GPU sanity checks.
*
return 0;
}
-
-/*!
- * \brief Runs a set of memory tests specified by the given bit-flags.
- * Tries to allocate and do the test on \p megs Mb memory or
- * the greatest amount that can be allocated (>10Mb).
- * In case if an error is detected it stops without finishing the remaining
- * steps/iterations and returns greater then zero value.
- * In case of other errors (e.g. kernel launch errors, device querying errors)
- * -1 is returned.
- *
- * \param[in] which_tests variable with bit-flags of the requested tests
- * \param[in] megs amount of memory that will be tested in MB
- * \param[in] iter number of iterations
- * \returns 0 if no error was detected, otherwise >0
- */
-static int do_memtest(unsigned int which_tests, int megs, int iter)
-{
- memtestState tester;
- int i;
- uint err_count; //, err_iter;
-
- // no parameter check as this fn won't be called externally
-
- // let's try to allocate the mem
- while (!tester.allocate(megs) && (megs - 10 > 0))
- {
- megs -= 10; tester.deallocate();
- }
-
- if (megs <= 10)
- {
- fprintf(stderr, "Unable to allocate GPU memory!\n");
- return -1;
- }
-
- // clear the first 18 bits
- which_tests &= 0x3FFF;
- for (i = 0; i < iter; i++)
- {
- // Moving Inversions (ones and zeros)
- if ((MOVING_INVERSIONS_10 & which_tests) == MOVING_INVERSIONS_10)
- {
- tester.gpuMovingInversionsOnesZeros(err_count);
- if (err_count > 0)
- {
- return MOVING_INVERSIONS_10;
- }
- }
- // Moving Inversions (random)
- if ((MOVING_INVERSIONS_RAND & which_tests) == MOVING_INVERSIONS_RAND)
- {
- tester.gpuMovingInversionsRandom(err_count);
- if (err_count > 0)
- {
- return MOVING_INVERSIONS_RAND;
- }
- }
- // Memtest86 Walking 8-bit
- if ((WALKING_8BIT_M86 & which_tests) == WALKING_8BIT_M86)
- {
- for (uint shift = 0; shift < 8; shift++)
- {
- tester.gpuWalking8BitM86(err_count, shift);
- if (err_count > 0)
- {
- return WALKING_8BIT_M86;
- }
- }
- }
- // True Walking zeros (8-bit)
- if ((WALKING_0_8BIT & which_tests) == WALKING_0_8BIT)
- {
- for (uint shift = 0; shift < 8; shift++)
- {
- tester.gpuWalking8Bit(err_count, false, shift);
- if (err_count > 0)
- {
- return WALKING_0_8BIT;
- }
- }
- }
- // True Walking ones (8-bit)
- if ((WALKING_1_8BIT & which_tests) == WALKING_1_8BIT)
- {
- for (uint shift = 0; shift < 8; shift++)
- {
- tester.gpuWalking8Bit(err_count, true, shift);
- if (err_count > 0)
- {
- return WALKING_1_8BIT;
- }
- }
- }
- // Memtest86 Walking zeros (32-bit)
- if ((WALKING_0_32BIT & which_tests) == WALKING_0_32BIT)
- {
- for (uint shift = 0; shift < 32; shift++)
- {
- tester.gpuWalking32Bit(err_count, false, shift);
- if (err_count > 0)
- {
- return WALKING_0_32BIT;
- }
- }
- }
- // Memtest86 Walking ones (32-bit)
- if ((WALKING_1_32BIT & which_tests) == WALKING_1_32BIT)
- {
- for (uint shift = 0; shift < 32; shift++)
- {
- tester.gpuWalking32Bit(err_count, true, shift);
- if (err_count > 0)
- {
- return WALKING_1_32BIT;
- }
- }
- }
- // Random blocks
- if ((RANDOM_BLOCKS & which_tests) == RANDOM_BLOCKS)
- {
- tester.gpuRandomBlocks(err_count, rand());
- if (err_count > 0)
- {
- return RANDOM_BLOCKS;
- }
-
- }
-
- // Memtest86 Modulo-20
- if ((MOD_20_32BIT & which_tests) == MOD_20_32BIT)
- {
- for (uint shift = 0; shift < 20; shift++)
- {
- tester.gpuModuloX(err_count, shift, rand(), 20, 2);
- if (err_count > 0)
- {
- return MOD_20_32BIT;
- }
- }
- }
- // Logic (one iteration)
- if ((LOGIC_1_ITER & which_tests) == LOGIC_1_ITER)
- {
- tester.gpuShortLCG0(err_count, 1);
- if (err_count > 0)
- {
- return LOGIC_1_ITER;
- }
- }
- // Logic (4 iterations)
- if ((LOGIC_4_ITER & which_tests) == LOGIC_4_ITER)
- {
- tester.gpuShortLCG0(err_count, 4);
- if (err_count > 0)
- {
- return LOGIC_4_ITER;
- }
-
- }
- // Logic (shared memory, one iteration)
- if ((LOGIC_1_ITER_SHMEM & which_tests) == LOGIC_1_ITER_SHMEM)
- {
- tester.gpuShortLCG0Shmem(err_count, 1);
- if (err_count > 0)
- {
- return LOGIC_1_ITER_SHMEM;
- }
- }
- // Logic (shared-memory, 4 iterations)
- if ((LOGIC_4_ITER_SHMEM & which_tests) == LOGIC_4_ITER_SHMEM)
- {
- tester.gpuShortLCG0Shmem(err_count, 4);
- if (err_count > 0)
- {
- return LOGIC_4_ITER_SHMEM;
- }
- }
- }
-
- tester.deallocate();
- return err_count;
-}
-
-/*! \brief Runs a quick memory test and returns 0 in case if no error is detected.
- * If an error is detected it stops before completing the test and returns a
- * value greater then 0. In case of other errors (e.g. kernel launch errors,
- * device querying errors) -1 is returned.
- *
- * \param[in] dev_id the device id of the GPU or -1 if the device has already been selected
- * \returns 0 if no error was detected, otherwise >0
- */
-int do_quick_memtest(int dev_id)
-{
- cudaDeviceProp dev_prop;
- int devmem, res, time = 0;
-
- if (debug)
- {
- time = getTimeMilliseconds();
- }
-
- if (do_sanity_checks(dev_id, &dev_prop) != 0)
- {
- // something went wrong
- return -1;
- }
-
- if (debug)
- {
- devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
- fprintf(debug, ">> Running QUICK memtests on %d MiB (out of total %d MiB), %d iterations\n",
- QUICK_MEM, devmem, QUICK_ITER);
- }
-
- res = do_memtest(QUICK_TESTS, QUICK_MEM, QUICK_ITER);
-
- if (debug)
- {
- fprintf(debug, "Q-RES = %d\n", res);
- fprintf(debug, "Q-runtime: %d ms\n", getTimeMilliseconds() - time);
- }
-
- /* destroy context only if we created it */
- if (dev_id != -1)
- {
- cudaThreadExit();
- }
- return res;
-}
-
-/*! \brief Runs a full memory test and returns 0 in case if no error is detected.
- * If an error is detected it stops before completing the test and returns a
- * value greater then 0. In case of other errors (e.g. kernel launch errors,
- * device querying errors) -1 is returned.
- *
- * \param[in] dev_id the device id of the GPU or -1 if the device has already been selected
- * \returns 0 if no error was detected, otherwise >0
- */
-
-int do_full_memtest(int dev_id)
-{
- cudaDeviceProp dev_prop;
- int devmem, res, time = 0;
-
- if (debug)
- {
- time = getTimeMilliseconds();
- }
-
- if (do_sanity_checks(dev_id, &dev_prop) != 0)
- {
- // something went wrong
- return -1;
- }
-
- devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-
- if (debug)
- {
- fprintf(debug, ">> Running FULL memtests on %d MiB (out of total %d MiB), %d iterations\n",
- devmem, devmem, FULL_ITER);
- }
-
- /* do all test on the entire memory */
- res = do_memtest(FULL_TESTS, devmem, FULL_ITER);
-
- if (debug)
- {
- fprintf(debug, "F-RES = %d\n", res);
- fprintf(debug, "F-runtime: %d ms\n", getTimeMilliseconds() - time);
- }
-
- /* destroy context only if we created it */
- if (dev_id != -1)
- {
- cudaThreadExit();
- }
- return res;
-}
-
-/*! \brief Runs a time constrained memory test and returns 0 in case if no error is detected.
- * If an error is detected it stops before completing the test and returns a value greater
- * than zero. In case of other errors (e.g. kernel launch errors, device querying errors) -1
- * is returned. Note, that test iterations are not interrupted therefor the total runtime of
- * the test will always be multipple of one iteration's runtime.
- *
- * \param[in] dev_id the device id of the GPU or -1 if the device has laredy been selected
- * \param[in] time_constr the time limit of the testing
- * \returns 0 if no error was detected, otherwise >0
- */
-int do_timed_memtest(int dev_id, int time_constr)
-{
- cudaDeviceProp dev_prop;
- int devmem, res = 0, time = 0, startt;
-
- if (debug)
- {
- time = getTimeMilliseconds();
- }
-
- time_constr *= 1000; /* convert to ms for convenience */
- startt = getTimeMilliseconds();
-
- if (do_sanity_checks(dev_id, &dev_prop) != 0)
- {
- // something went wrong
- return -1;
- }
-
- devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-
- if (debug)
- {
- fprintf(debug, ">> Running time constrained memtests on %d MiB (out of total %d MiB), time limit of %d s \n",
- devmem, devmem, time_constr);
- }
-
- /* do the TIMED_TESTS set, one step at a time on the entire memory
- that can be allocated, and stop when the given time is exceeded */
- while ( ((int)getTimeMilliseconds() - startt) < time_constr)
- {
- res = do_memtest(TIMED_TESTS, devmem, 1);
- if (res != 0)
- {
- break;
- }
- }
-
- if (debug)
- {
- fprintf(debug, "T-RES = %d\n", res);
- fprintf(debug, "T-runtime: %d ms\n", getTimeMilliseconds() - time);
- }
-
- /* destroy context only if we created it */
- if (dev_id != -1)
- {
- cudaThreadExit();
- }
- return res;
-}
-
/*! \brief Initializes the GPU with the given index.
*
* The varible \mygpu is the index of the GPU to initialize in the