package org.nd4j.nativeblas; import lombok.extern.slf4j.Slf4j; import org.bytedeco.javacpp.Loader; import org.bytedeco.javacpp.Pointer; import org.nd4j.linalg.api.blas.Blas; /** * CBlas bindings * * Original credit: * https://github.com/uncomplicate/neanderthal-atlas */ @Slf4j public abstract class Nd4jBlas implements Blas { public Nd4jBlas() { int numThreads; String skipper = System.getenv("ND4J_SKIP_BLAS_THREADS"); if (skipper == null || skipper.isEmpty()) { String numThreadsString = System.getenv("OMP_NUM_THREADS"); if (numThreadsString != null && !numThreadsString.isEmpty()) { numThreads = Integer.parseInt(numThreadsString); setMaxThreads(numThreads); } else { int cores = Loader.totalCores(); int chips = Loader.totalChips(); if (cores > 0 && chips > 0) numThreads = Math.max(1, cores /chips); else numThreads = getCores(Runtime.getRuntime().availableProcessors()); setMaxThreads(numThreads); } log.info("Number of threads used for BLAS: {}", getMaxThreads()); } } private int getCores(int totals) { // that's special case for Xeon Phi if (totals >= 256) return 64; int ht_off = totals / 2; // we count off HyperThreading without any excuses if (ht_off <= 4) return 4; // special case for Intel i5. and nobody likes i3 anyway if (ht_off > 24) { int rounds = 0; while (ht_off > 24) { // we loop until final value gets below 24 cores, since that's reasonable threshold as of 2016 if (ht_off > 24) { ht_off /= 2; // we dont' have any cpus that has higher number then 24 physical cores rounds++; } } // 20 threads is special case in this branch if (ht_off == 20 && rounds < 2) ht_off /= 2; } else { // low-core models are known, but there's a gap, between consumer cpus and xeons if (ht_off <= 6) { // that's more likely consumer-grade cpu, so leave this value alone return ht_off; } else { if (isOdd(ht_off)) // if that's odd number, it's final result return ht_off; // 20 threads & 16 threads are special case in this branch, where we go min value if (ht_off == 20 || ht_off == 16) ht_off /= 2; } } return ht_off; } /** * Returns the BLAS library vendor * * @return the BLAS library vendor */ @Override public Vendor getBlasVendor() { int vendor = getBlasVendorId(); boolean isUnknowVendor = ((vendor > Vendor.values().length - 1) || (vendor <= 0)); if (isUnknowVendor) { return Vendor.UNKNOWN; } return Vendor.values()[vendor]; } private boolean isOdd(int value) { return (value % 2 != 0); } }