- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using Intel MKL dgesvd in the code below. When comparing the results with Matlab, the singular values are ok, while the singular vectors are not.
The C++ code I'm using
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <mkl.h>
#include "mkl_lapacke.h"
#include "TimingCPU.h"
#include "InputOutput.h"
using namespace std;
/**********************************/
/* RANDOM MATRIX ENTRY GENERATION */
/**********************************/
double generateRandomMatrixEntry(int N) { return 2000. * ((double)rand() / (double)(RAND_MAX - 0.2) * (1. / (double)N)) + 100.*((double)rand() / (double)(RAND_MAX - 0.2) * (1. / (double)N)) + 24.; }
/********/
/* MAIN */
/********/
int main(int argc, char **argv) {
int Nrows, Ncols, K, numExecutions;
char *jobu = "S", *jobvt = "S"; // --- "N" means not to calculate the corresponding singular vectors
TimingCPU timer;
if (argc != 5) { printf("usage: svdMKLDouble Nrows Ncols K numExecutions\n"); exit(0); }
{ std::stringstream ss(argv[1]); ss >> Nrows; }
{ std::stringstream ss(argv[2]); ss >> Ncols; }
{ std::stringstream ss(argv[3]); ss >> K; }
{ std::stringstream ss(argv[4]); ss >> numExecutions; }
int lda = Nrows, ldu = Nrows, ldvt = Ncols;
double TotalTime = 0., AverageTime = 0.;
double *A = (double*)mkl_malloc(Nrows * Ncols * K * sizeof(double), 64); // --- Input matrices
double *A_QUERY = (double*)mkl_malloc(Nrows * Ncols * sizeof(double), 64); // --- Input matrix for MKL query
double *U = (double*)mkl_malloc(Nrows * Nrows * K * sizeof(double), 64); // --- Matrices of LEFT singular vectors
double *S = (double*)mkl_malloc( Ncols * K * sizeof(double), 64); // --- Singular values
double *V = (double*)mkl_malloc(Ncols * Ncols * K * sizeof(double), 64); // --- Matrices of RIGHT singular vectors
srand(time(NULL));
//srand(0);
int N = 5;
/*************************************************/
/* QUERY AND ALLOCATION OF THE OPTIMAL WORKSPACE */
/*************************************************/
for (int h = 0; h < Nrows * Ncols; h++) A_QUERY = generateRandomMatrixEntry(N);
int info, lwork = -1;
double wkopt;
dgesvd(jobu, jobvt, &Nrows, &Ncols, A_QUERY, &lda, S, U, &ldu, V, &ldvt, &wkopt, &lwork, &info);
lwork = (int)wkopt;
double *work = (double *)malloc(lwork * K * sizeof(double));
/**************/
/* DUMMY CALL */
/**************/
for (int i = 0; i < K; i++)
dgesvd(jobu, jobvt, &Nrows, &Ncols, A + (i * Nrows * Ncols), &lda, S + (i * Ncols), U + (i * Nrows * Nrows), &ldu, V + (i * Ncols * Ncols), &ldvt, work + i * lwork, &lwork, &info);
/*********************/
/* TIME MEASUREMENTS */
/*********************/
for (int k = 0; k < numExecutions; k++) {
//srand(k);
for (int h = 0; h < Nrows * Ncols * K; h++) { A = generateRandomMatrixEntry(N); }
timer.StartCounter();
#pragma omp parallel for
for (int i = 0; i < K; i++) {
dgesvd(jobu, jobvt, &Nrows, &Ncols, A + (i * Nrows * Ncols), &lda, S + (i * Ncols), U + (i * Nrows * Nrows), &ldu, V + (i * Ncols * Ncols), &ldvt, work + i * lwork, &lwork, &info);
// --- Convergence check
if (info > 0) { printf("Convergence failure.\n"); exit(1); }
}
#pragma omp barrier
TotalTime += timer.GetCounter(); // --- TotalTime in ms
}
AverageTime = TotalTime / numExecutions;
std::cout << std::scientific << Nrows << " " << Ncols << " " << K << " " << numExecutions << " " << AverageTime << " " << std::endl;
/*****************************/
/* SAVINGS FOR RESULT CHECKS */
/*****************************/
// --- Saving the last matrix
saveCPUrealtxt<double>(A + ((K - 1) * Nrows * Ncols), "Source_Matrix.txt", Nrows * Ncols);
// --- Saving the SVD
saveCPUrealtxt<double>(U + ((K - 1) * Nrows * Nrows), "U.txt", Nrows * Nrows);
saveCPUrealtxt<double>(V + ((K - 1) * Ncols * Ncols), "V.txt", Ncols * Ncols);
saveCPUrealtxt<double>(S + ((K - 1) * Ncols), "S.txt", Ncols );
return 0;
}
The compilation command
icpc -lpthread -lmkl_sequential -lmkl_core -lmkl_intel_lp64 -lrt -openmp svdMKLDouble.cpp TimingCPU.cpp InputOutput.cpp -O3 -o svdMKLDouble
Code usage as...
./svdMKLDouble 8 8 1 1
The Matlab code I'm using as reference
clear all close all clc load Source_Matrix.txt load U.txt load V.txt load S.txt Source_Matrix = reshape(Source_Matrix, 8, 8); U = reshape(U, 8, 8); V = reshape(V, 8, 8); [UU, SS, VV] = svd(Source_Matrix); 100 * sqrt(sum(abs(diag(SS) - S).^2) / sum(abs(diag(SS)).^2)) 100 * sqrt(sum(sum((abs(Source_Matrix - UU * SS * VV.').^2))) / sum(sum((abs(Source_Matrix).^2)))) 100 * sqrt(sum(sum((abs(Source_Matrix - U * diag(S) * V).^2))) / sum(sum((abs(Source_Matrix).^2))))
The comparison results
ans =
0.0512 ---> Singular values correctly computed
ans =
5.1387e-13 ---> Matlab SVD works correctly
ans =
132.3127 ---> Intel MKL singular values do not seem to be correct
The question: What I'm doing wrong?
Link Copied
0 Replies
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page